From 5af2cd6f26ce01294ceff8292fcc1b217c6978b0 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Sat, 6 Apr 2019 11:02:15 -0400 Subject: [PATCH] gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 --- go.mod | 2 +- go.sum | 4 +- .../src/k8s.io/apiextensions-apiserver/go.mod | 2 +- .../src/k8s.io/apiextensions-apiserver/go.sum | 2 +- staging/src/k8s.io/code-generator/go.mod | 2 +- staging/src/k8s.io/code-generator/go.sum | 4 +- staging/src/k8s.io/kube-aggregator/go.mod | 2 +- staging/src/k8s.io/kube-aggregator/go.sum | 2 +- staging/src/k8s.io/metrics/go.mod | 2 +- staging/src/k8s.io/metrics/go.sum | 2 +- staging/src/k8s.io/node-api/go.mod | 2 +- staging/src/k8s.io/node-api/go.sum | 2 +- staging/src/k8s.io/sample-apiserver/go.mod | 2 +- staging/src/k8s.io/sample-apiserver/go.sum | 2 +- staging/src/k8s.io/sample-controller/go.mod | 2 +- staging/src/k8s.io/sample-controller/go.sum | 2 +- vendor/BUILD | 2 + vendor/gonum.org/v1/gonum/AUTHORS | 25 +- vendor/gonum.org/v1/gonum/CONTRIBUTORS | 22 +- vendor/gonum.org/v1/gonum/blas/BUILD | 1 + vendor/gonum.org/v1/gonum/blas/blas.go | 40 +- .../gonum.org/v1/gonum/blas/blas64/blas64.go | 104 +- vendor/gonum.org/v1/gonum/blas/cblas128/BUILD | 33 + .../v1/gonum/blas/cblas128/cblas128.go | 508 +++ .../gonum.org/v1/gonum/blas/cblas128/conv.go | 279 ++ .../v1/gonum/blas/cblas128/conv_hermitian.go | 155 + .../v1/gonum/blas/cblas128/conv_symmetric.go | 155 + .../gonum.org/v1/gonum/blas/cblas128/doc.go | 6 + vendor/gonum.org/v1/gonum/blas/gonum/BUILD | 28 +- vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go | 164 - vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go | 81 +- .../gonum.org/v1/gonum/blas/gonum/errors.go | 35 + vendor/gonum.org/v1/gonum/blas/gonum/gemv.go | 56 +- vendor/gonum.org/v1/gonum/blas/gonum/gonum.go | 144 +- .../v1/gonum/blas/gonum/level1cmplx128.go | 43 +- .../v1/gonum/blas/gonum/level1cmplx64.go | 467 +++ .../{level1single.go => level1float32.go} | 64 +- ...single_dsdot.go => level1float32_dsdot.go} | 10 +- ...l1single_sdot.go => level1float32_sdot.go} | 10 +- ...ngle_sdsdot.go => level1float32_sdsdot.go} | 10 +- .../{level1double.go => level1float64.go} | 64 +- ...l1double_ddot.go => level1float64_ddot.go} | 10 +- .../v1/gonum/blas/gonum/level2cmplx128.go | 753 ++++- .../v1/gonum/blas/gonum/level2cmplx64.go | 2942 +++++++++++++++++ .../{level2single.go => level2float32.go} | 500 ++- .../{level2double.go => level2float64.go} | 500 ++- .../v1/gonum/blas/gonum/level3cmplx128.go | 1715 ++++++++++ .../v1/gonum/blas/gonum/level3cmplx64.go | 1735 ++++++++++ .../{level3single.go => level3float32.go} | 323 +- .../{level3double.go => level3float64.go} | 323 +- vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go | 81 +- .../v1/gonum/blas/gonum/single_precision.bash | 153 +- vendor/gonum.org/v1/gonum/floats/floats.go | 23 +- vendor/gonum.org/v1/gonum/graph/BUILD | 2 + vendor/gonum.org/v1/gonum/graph/doc.go | 3 + .../v1/gonum/graph/encoding/dot/BUILD | 1 - .../v1/gonum/graph/encoding/dot/decode.go | 256 +- .../v1/gonum/graph/encoding/dot/doc.go | 9 +- .../v1/gonum/graph/encoding/dot/encode.go | 382 ++- .../v1/gonum/graph/encoding/encoding.go | 6 + .../formats/dot/internal/errors/errors.go | 6 +- .../formats/dot/internal/parser/parser.go | 4 +- vendor/gonum.org/v1/gonum/graph/graph.go | 69 +- .../v1/gonum/graph/internal/ordered/sort.go | 17 + .../v1/gonum/graph/internal/set/set.go | 100 +- .../gonum.org/v1/gonum/graph/iterator/BUILD | 29 + .../gonum.org/v1/gonum/graph/iterator/doc.go | 9 + .../v1/gonum/graph/iterator/edges.go | 131 + .../v1/gonum/graph/iterator/lines.go | 131 + .../v1/gonum/graph/iterator/nodes.go | 125 + vendor/gonum.org/v1/gonum/graph/multigraph.go | 56 +- .../gonum.org/v1/gonum/graph/nodes_edges.go | 300 ++ vendor/gonum.org/v1/gonum/graph/simple/BUILD | 1 + .../graph/simple/dense_directed_matrix.go | 282 +- .../graph/simple/dense_undirected_matrix.go | 259 +- .../v1/gonum/graph/simple/directed.go | 251 +- vendor/gonum.org/v1/gonum/graph/simple/doc.go | 2 + .../gonum.org/v1/gonum/graph/simple/simple.go | 21 + .../v1/gonum/graph/simple/undirected.go | 253 +- .../gonum/graph/simple/weighted_directed.go | 284 +- .../gonum/graph/simple/weighted_undirected.go | 314 +- vendor/gonum.org/v1/gonum/graph/topo/BUILD | 1 + .../v1/gonum/graph/topo/bron_kerbosch.go | 30 +- .../v1/gonum/graph/topo/clique_graph.go | 9 +- .../v1/gonum/graph/topo/johnson_cycles.go | 20 +- .../v1/gonum/graph/topo/paton_cycles.go | 6 +- .../gonum.org/v1/gonum/graph/topo/tarjan.go | 8 +- vendor/gonum.org/v1/gonum/graph/topo/topo.go | 2 +- .../v1/gonum/graph/traverse/traverse.go | 82 +- vendor/gonum.org/v1/gonum/graph/undirect.go | 120 +- .../gonum.org/v1/gonum/internal/asm/c64/BUILD | 37 + .../v1/gonum/internal/asm/c64/axpyinc_amd64.s | 151 + .../gonum/internal/asm/c64/axpyincto_amd64.s | 156 + .../internal/asm/c64/axpyunitary_amd64.s | 160 + .../internal/asm/c64/axpyunitaryto_amd64.s | 157 + .../dot/dot.go => internal/asm/c64/conj.go} | 4 +- .../v1/gonum/internal/asm/c64/doc.go | 6 + .../v1/gonum/internal/asm/c64/dotcinc_amd64.s | 160 + .../internal/asm/c64/dotcunitary_amd64.s | 208 ++ .../v1/gonum/internal/asm/c64/dotuinc_amd64.s | 148 + .../internal/asm/c64/dotuunitary_amd64.s | 197 ++ .../v1/gonum/internal/asm/c64/scal.go | 79 + .../v1/gonum/internal/asm/c64/stubs_amd64.go | 68 + .../v1/gonum/internal/asm/c64/stubs_noasm.go | 113 + .../gonum.org/v1/gonum/internal/asm/f64/BUILD | 1 + .../v1/gonum/internal/asm/f64/ge_noasm.go | 2 +- .../v1/gonum/internal/asm/f64/gemvN_amd64.s | 2 +- .../v1/gonum/internal/asm/f64/gemvT_amd64.s | 2 +- .../v1/gonum/internal/asm/f64/stubs_amd64.go | 7 + .../v1/gonum/internal/asm/f64/stubs_noasm.go | 13 + .../v1/gonum/internal/asm/f64/sum_amd64.s | 100 + .../gonum.org/v1/gonum/internal/cmplx64/BUILD | 31 + .../v1/gonum/internal/cmplx64/abs.go | 14 + .../v1/gonum/internal/cmplx64/conj.go | 12 + .../v1/gonum/internal/cmplx64/doc.go | 7 + .../v1/gonum/internal/cmplx64/isinf.go | 25 + .../v1/gonum/internal/cmplx64/isnan.go | 29 + .../v1/gonum/internal/cmplx64/sqrt.go | 108 + vendor/gonum.org/v1/gonum/lapack/gonum/BUILD | 7 +- .../gonum.org/v1/gonum/lapack/gonum/dbdsqr.go | 67 +- .../gonum.org/v1/gonum/lapack/gonum/dgebak.go | 43 +- .../gonum.org/v1/gonum/lapack/gonum/dgebal.go | 35 +- .../gonum.org/v1/gonum/lapack/gonum/dgebd2.go | 38 +- .../gonum.org/v1/gonum/lapack/gonum/dgebrd.go | 83 +- .../gonum.org/v1/gonum/lapack/gonum/dgecon.go | 29 +- .../gonum.org/v1/gonum/lapack/gonum/dgeev.go | 109 +- .../gonum.org/v1/gonum/lapack/gonum/dgehd2.go | 23 +- .../gonum.org/v1/gonum/lapack/gonum/dgehrd.go | 23 +- .../gonum.org/v1/gonum/lapack/gonum/dgelq2.go | 26 +- .../gonum.org/v1/gonum/lapack/gonum/dgelqf.go | 47 +- .../gonum.org/v1/gonum/lapack/gonum/dgels.go | 63 +- .../gonum.org/v1/gonum/lapack/gonum/dgeql2.go | 28 +- .../gonum.org/v1/gonum/lapack/gonum/dgeqp3.go | 58 +- .../gonum.org/v1/gonum/lapack/gonum/dgeqr2.go | 27 +- .../gonum.org/v1/gonum/lapack/gonum/dgeqrf.go | 52 +- .../gonum.org/v1/gonum/lapack/gonum/dgerq2.go | 27 +- .../gonum.org/v1/gonum/lapack/gonum/dgerqf.go | 39 +- .../gonum.org/v1/gonum/lapack/gonum/dgesvd.go | 264 +- .../gonum.org/v1/gonum/lapack/gonum/dgetf2.go | 23 +- .../gonum.org/v1/gonum/lapack/gonum/dgetrf.go | 29 +- .../gonum.org/v1/gonum/lapack/gonum/dgetri.go | 66 +- .../gonum.org/v1/gonum/lapack/gonum/dgetrs.go | 29 +- .../v1/gonum/lapack/gonum/dggsvd3.go | 80 +- .../v1/gonum/lapack/gonum/dggsvp3.go | 84 +- .../gonum.org/v1/gonum/lapack/gonum/dhseqr.go | 93 +- .../gonum.org/v1/gonum/lapack/gonum/dlabrd.go | 53 +- .../gonum.org/v1/gonum/lapack/gonum/dlacn2.go | 32 +- .../gonum.org/v1/gonum/lapack/gonum/dlacpy.go | 29 +- .../gonum.org/v1/gonum/lapack/gonum/dlaexc.go | 38 +- .../gonum.org/v1/gonum/lapack/gonum/dlahqr.go | 44 +- .../gonum.org/v1/gonum/lapack/gonum/dlahr2.go | 38 +- .../gonum.org/v1/gonum/lapack/gonum/dlaln2.go | 25 +- .../gonum.org/v1/gonum/lapack/gonum/dlange.go | 45 +- .../gonum.org/v1/gonum/lapack/gonum/dlanst.go | 21 +- .../gonum.org/v1/gonum/lapack/gonum/dlansy.go | 29 +- .../gonum.org/v1/gonum/lapack/gonum/dlantr.go | 46 +- .../gonum.org/v1/gonum/lapack/gonum/dlapll.go | 25 +- .../gonum.org/v1/gonum/lapack/gonum/dlapmt.go | 25 +- .../gonum.org/v1/gonum/lapack/gonum/dlaqp2.go | 44 +- .../gonum.org/v1/gonum/lapack/gonum/dlaqps.go | 59 +- .../v1/gonum/lapack/gonum/dlaqr04.go | 71 +- .../gonum.org/v1/gonum/lapack/gonum/dlaqr1.go | 18 +- .../v1/gonum/lapack/gonum/dlaqr23.go | 90 +- .../gonum.org/v1/gonum/lapack/gonum/dlaqr5.go | 98 +- .../gonum.org/v1/gonum/lapack/gonum/dlarf.go | 30 +- .../gonum.org/v1/gonum/lapack/gonum/dlarfb.go | 66 +- .../gonum.org/v1/gonum/lapack/gonum/dlarfg.go | 13 +- .../gonum.org/v1/gonum/lapack/gonum/dlarft.go | 44 +- .../gonum.org/v1/gonum/lapack/gonum/dlarfx.go | 41 +- .../gonum.org/v1/gonum/lapack/gonum/dlascl.go | 36 +- .../gonum.org/v1/gonum/lapack/gonum/dlaset.go | 21 +- .../gonum.org/v1/gonum/lapack/gonum/dlasq1.go | 23 +- .../gonum.org/v1/gonum/lapack/gonum/dlasq2.go | 31 +- .../gonum.org/v1/gonum/lapack/gonum/dlasq3.go | 11 + .../gonum.org/v1/gonum/lapack/gonum/dlasq4.go | 11 + .../gonum.org/v1/gonum/lapack/gonum/dlasq5.go | 13 + .../gonum.org/v1/gonum/lapack/gonum/dlasq6.go | 13 +- .../gonum.org/v1/gonum/lapack/gonum/dlasr.go | 55 +- .../gonum.org/v1/gonum/lapack/gonum/dlasrt.go | 8 +- .../gonum.org/v1/gonum/lapack/gonum/dlassq.go | 12 +- .../gonum.org/v1/gonum/lapack/gonum/dlaswp.go | 7 +- .../gonum.org/v1/gonum/lapack/gonum/dlatrd.go | 36 +- .../gonum.org/v1/gonum/lapack/gonum/dlatrs.go | 43 +- .../gonum.org/v1/gonum/lapack/gonum/dlauu2.go | 64 + .../gonum.org/v1/gonum/lapack/gonum/dlauum.go | 81 + vendor/gonum.org/v1/gonum/lapack/gonum/doc.go | 2 +- .../gonum.org/v1/gonum/lapack/gonum/dorg2l.go | 33 +- .../gonum.org/v1/gonum/lapack/gonum/dorg2r.go | 38 +- .../gonum.org/v1/gonum/lapack/gonum/dorgbr.go | 82 +- .../gonum.org/v1/gonum/lapack/gonum/dorghr.go | 20 +- .../gonum.org/v1/gonum/lapack/gonum/dorgl2.go | 36 +- .../gonum.org/v1/gonum/lapack/gonum/dorglq.go | 112 +- .../gonum.org/v1/gonum/lapack/gonum/dorgql.go | 30 +- .../gonum.org/v1/gonum/lapack/gonum/dorgqr.go | 124 +- .../gonum.org/v1/gonum/lapack/gonum/dorgtr.go | 33 +- .../gonum.org/v1/gonum/lapack/gonum/dorm2r.go | 59 +- .../gonum.org/v1/gonum/lapack/gonum/dormbr.go | 82 +- .../gonum.org/v1/gonum/lapack/gonum/dormhr.go | 46 +- .../gonum.org/v1/gonum/lapack/gonum/dorml2.go | 61 +- .../gonum.org/v1/gonum/lapack/gonum/dormlq.go | 67 +- .../gonum.org/v1/gonum/lapack/gonum/dormqr.go | 68 +- .../gonum.org/v1/gonum/lapack/gonum/dormr2.go | 66 +- .../gonum.org/v1/gonum/lapack/gonum/dpbtf2.go | 17 +- .../gonum.org/v1/gonum/lapack/gonum/dpocon.go | 52 +- .../gonum.org/v1/gonum/lapack/gonum/dpotf2.go | 14 +- .../gonum.org/v1/gonum/lapack/gonum/dpotrf.go | 13 +- .../gonum.org/v1/gonum/lapack/gonum/dpotri.go | 44 + .../gonum.org/v1/gonum/lapack/gonum/dpotrs.go | 62 + .../gonum.org/v1/gonum/lapack/gonum/drscl.go | 18 +- .../gonum.org/v1/gonum/lapack/gonum/dsteqr.go | 57 +- .../gonum.org/v1/gonum/lapack/gonum/dsterf.go | 15 +- .../gonum.org/v1/gonum/lapack/gonum/dsyev.go | 55 +- .../gonum.org/v1/gonum/lapack/gonum/dsytd2.go | 43 +- .../gonum.org/v1/gonum/lapack/gonum/dsytrd.go | 68 +- .../gonum.org/v1/gonum/lapack/gonum/dtgsja.go | 76 +- .../gonum.org/v1/gonum/lapack/gonum/dtrcon.go | 30 +- .../v1/gonum/lapack/gonum/dtrevc3.go | 214 +- .../gonum.org/v1/gonum/lapack/gonum/dtrexc.go | 59 +- .../gonum.org/v1/gonum/lapack/gonum/dtrti2.go | 20 +- .../gonum.org/v1/gonum/lapack/gonum/dtrtri.go | 22 +- .../gonum.org/v1/gonum/lapack/gonum/dtrtrs.go | 31 +- .../gonum.org/v1/gonum/lapack/gonum/errors.go | 174 + .../v1/gonum/lapack/gonum/general.go | 143 - .../gonum.org/v1/gonum/lapack/gonum/iladlc.go | 18 +- .../gonum.org/v1/gonum/lapack/gonum/iladlr.go | 17 +- .../gonum.org/v1/gonum/lapack/gonum/ilaenv.go | 88 +- .../gonum.org/v1/gonum/lapack/gonum/iparmq.go | 4 +- .../gonum.org/v1/gonum/lapack/gonum/lapack.go | 51 + vendor/gonum.org/v1/gonum/lapack/lapack.go | 157 +- .../v1/gonum/lapack/lapack64/lapack64.go | 104 +- vendor/gonum.org/v1/gonum/mat/BUILD | 4 + vendor/gonum.org/v1/gonum/mat/band.go | 37 +- vendor/gonum.org/v1/gonum/mat/cdense.go | 168 + vendor/gonum.org/v1/gonum/mat/cholesky.go | 234 +- vendor/gonum.org/v1/gonum/mat/cmatrix.go | 145 +- vendor/gonum.org/v1/gonum/mat/consts.go | 39 - vendor/gonum.org/v1/gonum/mat/dense.go | 87 +- .../v1/gonum/mat/dense_arithmetic.go | 55 +- vendor/gonum.org/v1/gonum/mat/diagonal.go | 311 ++ vendor/gonum.org/v1/gonum/mat/eigen.go | 203 +- vendor/gonum.org/v1/gonum/mat/errors.go | 1 + vendor/gonum.org/v1/gonum/mat/format.go | 2 +- vendor/gonum.org/v1/gonum/mat/gsvd.go | 76 +- vendor/gonum.org/v1/gonum/mat/hogsvd.go | 42 +- .../v1/gonum/mat/index_bound_checks.go | 119 +- .../v1/gonum/mat/index_no_bound_checks.go | 128 +- vendor/gonum.org/v1/gonum/mat/io.go | 10 +- vendor/gonum.org/v1/gonum/mat/lq.go | 63 +- vendor/gonum.org/v1/gonum/mat/lu.go | 96 +- vendor/gonum.org/v1/gonum/mat/matrix.go | 146 +- vendor/gonum.org/v1/gonum/mat/pool.go | 2 +- vendor/gonum.org/v1/gonum/mat/qr.go | 63 +- vendor/gonum.org/v1/gonum/mat/solve.go | 8 +- vendor/gonum.org/v1/gonum/mat/svd.go | 169 +- vendor/gonum.org/v1/gonum/mat/symband.go | 70 +- vendor/gonum.org/v1/gonum/mat/symmetric.go | 74 +- vendor/gonum.org/v1/gonum/mat/triangular.go | 75 +- vendor/gonum.org/v1/gonum/mat/triband.go | 353 ++ vendor/gonum.org/v1/gonum/mat/vector.go | 53 +- vendor/modules.txt | 6 +- 260 files changed, 20687 insertions(+), 4936 deletions(-) create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/BUILD create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go create mode 100644 vendor/gonum.org/v1/gonum/blas/cblas128/doc.go delete mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/errors.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go rename vendor/gonum.org/v1/gonum/blas/gonum/{level1single.go => level1float32.go} (89%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level1single_dsdot.go => level1float32_dsdot.go} (90%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level1single_sdot.go => level1float32_sdot.go} (90%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level1single_sdsdot.go => level1float32_sdsdot.go} (90%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level1double.go => level1float64.go} (89%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level1double_ddot.go => level1float64_ddot.go} (89%) create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go rename vendor/gonum.org/v1/gonum/blas/gonum/{level2single.go => level2float32.go} (82%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level2double.go => level2float64.go} (81%) create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go create mode 100644 vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go rename vendor/gonum.org/v1/gonum/blas/gonum/{level3single.go => level3float32.go} (78%) rename vendor/gonum.org/v1/gonum/blas/gonum/{level3double.go => level3float64.go} (77%) create mode 100644 vendor/gonum.org/v1/gonum/graph/iterator/BUILD create mode 100644 vendor/gonum.org/v1/gonum/graph/iterator/doc.go create mode 100644 vendor/gonum.org/v1/gonum/graph/iterator/edges.go create mode 100644 vendor/gonum.org/v1/gonum/graph/iterator/lines.go create mode 100644 vendor/gonum.org/v1/gonum/graph/iterator/nodes.go create mode 100644 vendor/gonum.org/v1/gonum/graph/nodes_edges.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/BUILD create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s rename vendor/gonum.org/v1/gonum/{graph/encoding/dot/dot.go => internal/asm/c64/conj.go} (66%) create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go create mode 100644 vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/BUILD create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go create mode 100644 vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/errors.go delete mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/general.go create mode 100644 vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go create mode 100644 vendor/gonum.org/v1/gonum/mat/cdense.go create mode 100644 vendor/gonum.org/v1/gonum/mat/diagonal.go create mode 100644 vendor/gonum.org/v1/gonum/mat/triband.go diff --git a/go.mod b/go.mod index 6b80cd90ea3..b5e8c9bd62e 100644 --- a/go.mod +++ b/go.mod @@ -442,7 +442,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/api => google.golang.org/api v0.0.0-20181220000619-583d854617af google.golang.org/appengine => google.golang.org/appengine v1.5.0 diff --git a/go.sum b/go.sum index 10c904c0f0e..ad5bc5653a4 100644 --- a/go.sum +++ b/go.sum @@ -454,8 +454,8 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc h1:54pjpwMXgPOGLujOy/QdrSB3aRqX3d0a3pNyCJq+a7c= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/api v0.0.0-20181220000619-583d854617af h1:iQMS7JKv/0w/iiWf1M49Cg3dmOkBoBZT5KheqPDpaac= diff --git a/staging/src/k8s.io/apiextensions-apiserver/go.mod b/staging/src/k8s.io/apiextensions-apiserver/go.mod index 75b7fef48f5..42104cf1e2f 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/go.mod +++ b/staging/src/k8s.io/apiextensions-apiserver/go.mod @@ -149,7 +149,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/appengine => google.golang.org/appengine v1.5.0 google.golang.org/genproto => google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6 diff --git a/staging/src/k8s.io/apiextensions-apiserver/go.sum b/staging/src/k8s.io/apiextensions-apiserver/go.sum index 8aa5c107385..01dc22eb433 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/go.sum +++ b/staging/src/k8s.io/apiextensions-apiserver/go.sum @@ -192,7 +192,7 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/staging/src/k8s.io/code-generator/go.mod b/staging/src/k8s.io/code-generator/go.mod index 7d849dacf17..28b9524dc2b 100644 --- a/staging/src/k8s.io/code-generator/go.mod +++ b/staging/src/k8s.io/code-generator/go.mod @@ -20,7 +20,7 @@ replace ( github.com/spf13/pflag => github.com/spf13/pflag v1.0.1 golang.org/x/exp => golang.org/x/exp v0.0.0-20180321215751-8460e604b9de golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e k8s.io/api => ../api k8s.io/apiextensions-apiserver => ../apiextensions-apiserver diff --git a/staging/src/k8s.io/code-generator/go.sum b/staging/src/k8s.io/code-generator/go.sum index 10b0b84f8f3..61ba0a66662 100644 --- a/staging/src/k8s.io/code-generator/go.sum +++ b/staging/src/k8s.io/code-generator/go.sum @@ -7,8 +7,8 @@ golang.org/x/exp v0.0.0-20180321215751-8460e604b9de h1:xSjD6HQTqT0H/k60N5yYBtnN1 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc h1:54pjpwMXgPOGLujOy/QdrSB3aRqX3d0a3pNyCJq+a7c= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e h1:jRyg0XfpwWlhEV8mDfdNGBeSJM2fuyh9Yjrnd8kF2Ts= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= k8s.io/gengo v0.0.0-20190116091435-f8a0810f38af h1:SwjZbO0u5ZuaV6TRMWOGB40iaycX8sbdMQHtjNZ19dk= diff --git a/staging/src/k8s.io/kube-aggregator/go.mod b/staging/src/k8s.io/kube-aggregator/go.mod index bb84390c4e3..ec8c67c6aa1 100644 --- a/staging/src/k8s.io/kube-aggregator/go.mod +++ b/staging/src/k8s.io/kube-aggregator/go.mod @@ -128,7 +128,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/appengine => google.golang.org/appengine v1.5.0 google.golang.org/genproto => google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6 diff --git a/staging/src/k8s.io/kube-aggregator/go.sum b/staging/src/k8s.io/kube-aggregator/go.sum index 6130f1914b0..3d953c3c63e 100644 --- a/staging/src/k8s.io/kube-aggregator/go.sum +++ b/staging/src/k8s.io/kube-aggregator/go.sum @@ -176,7 +176,7 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/staging/src/k8s.io/metrics/go.mod b/staging/src/k8s.io/metrics/go.mod index bb7265d886c..7c6f2104b77 100644 --- a/staging/src/k8s.io/metrics/go.mod +++ b/staging/src/k8s.io/metrics/go.mod @@ -54,7 +54,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/appengine => google.golang.org/appengine v1.5.0 gopkg.in/check.v1 => gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 diff --git a/staging/src/k8s.io/metrics/go.sum b/staging/src/k8s.io/metrics/go.sum index abc12d27b83..fc686b7db2d 100644 --- a/staging/src/k8s.io/metrics/go.sum +++ b/staging/src/k8s.io/metrics/go.sum @@ -60,7 +60,7 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/staging/src/k8s.io/node-api/go.mod b/staging/src/k8s.io/node-api/go.mod index 7a0df5a2727..dfa7c744fd8 100644 --- a/staging/src/k8s.io/node-api/go.mod +++ b/staging/src/k8s.io/node-api/go.mod @@ -51,7 +51,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/appengine => google.golang.org/appengine v1.5.0 gopkg.in/check.v1 => gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 diff --git a/staging/src/k8s.io/node-api/go.sum b/staging/src/k8s.io/node-api/go.sum index 3809a4df5c0..0ac5d8389c6 100644 --- a/staging/src/k8s.io/node-api/go.sum +++ b/staging/src/k8s.io/node-api/go.sum @@ -62,7 +62,7 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/staging/src/k8s.io/sample-apiserver/go.mod b/staging/src/k8s.io/sample-apiserver/go.mod index 84b29d5a01a..e5c2ac5c2f5 100644 --- a/staging/src/k8s.io/sample-apiserver/go.mod +++ b/staging/src/k8s.io/sample-apiserver/go.mod @@ -118,7 +118,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/appengine => google.golang.org/appengine v1.5.0 google.golang.org/genproto => google.golang.org/genproto v0.0.0-20170731182057-09f6ed296fc6 diff --git a/staging/src/k8s.io/sample-apiserver/go.sum b/staging/src/k8s.io/sample-apiserver/go.sum index 0e1b6a3ce35..94a5ef024f8 100644 --- a/staging/src/k8s.io/sample-apiserver/go.sum +++ b/staging/src/k8s.io/sample-apiserver/go.sum @@ -173,7 +173,7 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/staging/src/k8s.io/sample-controller/go.mod b/staging/src/k8s.io/sample-controller/go.mod index 7ea997d9924..3e75b998ae3 100644 --- a/staging/src/k8s.io/sample-controller/go.mod +++ b/staging/src/k8s.io/sample-controller/go.mod @@ -53,7 +53,7 @@ replace ( golang.org/x/text => golang.org/x/text v0.0.0-20170810154203-b19bf474d317 golang.org/x/time => golang.org/x/time v0.0.0-20161028155119-f51c12702a4d golang.org/x/tools => golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd - gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc + gonum.org/v1/gonum => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/netlib => gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e google.golang.org/appengine => google.golang.org/appengine v1.5.0 gopkg.in/check.v1 => gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 diff --git a/staging/src/k8s.io/sample-controller/go.sum b/staging/src/k8s.io/sample-controller/go.sum index e56adc3f121..c2058715dd8 100644 --- a/staging/src/k8s.io/sample-controller/go.sum +++ b/staging/src/k8s.io/sample-controller/go.sum @@ -63,7 +63,7 @@ golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wk golang.org/x/time v0.0.0-20161028155119-f51c12702a4d/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd h1:Es0jGqKF2dQq+Z+0JvLFrUgmuMpgFwsFnKJQiaKEJNU= golang.org/x/tools v0.0.0-20190205050122-7f7074d5bcfd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/vendor/BUILD b/vendor/BUILD index 3bb56021eb1..8d8354db68d 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -437,8 +437,10 @@ filegroup( "//vendor/gonum.org/v1/gonum/floats:all-srcs", "//vendor/gonum.org/v1/gonum/graph:all-srcs", "//vendor/gonum.org/v1/gonum/internal/asm/c128:all-srcs", + "//vendor/gonum.org/v1/gonum/internal/asm/c64:all-srcs", "//vendor/gonum.org/v1/gonum/internal/asm/f32:all-srcs", "//vendor/gonum.org/v1/gonum/internal/asm/f64:all-srcs", + "//vendor/gonum.org/v1/gonum/internal/cmplx64:all-srcs", "//vendor/gonum.org/v1/gonum/internal/math32:all-srcs", "//vendor/gonum.org/v1/gonum/lapack:all-srcs", "//vendor/gonum.org/v1/gonum/mat:all-srcs", diff --git a/vendor/gonum.org/v1/gonum/AUTHORS b/vendor/gonum.org/v1/gonum/AUTHORS index dd17494a85a..417db9b8903 100644 --- a/vendor/gonum.org/v1/gonum/AUTHORS +++ b/vendor/gonum.org/v1/gonum/AUTHORS @@ -8,16 +8,22 @@ # Please keep the list sorted. -Brendan Tracey +Alexander Egurnov Bill Gray Bill Noon +Brendan Tracey +Brent Pedersen Chad Kunde Chih-Wei Chang Chris Tessum +Christophe Meessen +Clayton Northey Dan Kortschak Daniel Fireman David Samborski Davor Kapsa +DeepMind Technologies +Dezmond Goff Egon Elbre Ekaterina Efimova Ethan Burns @@ -28,6 +34,8 @@ Francesc Campoy Google Inc Gustaf Johansson Iakov Davydov +Igor Mikushkin +Iskander Sharipov Jalem Raj Rohit James Bell James Bowman @@ -36,35 +44,46 @@ Janne Snabb Jeff Juozapaitis Jeremy Atkinson Jonas Kahler +Jonas Schulze Jonathan J Lawlor Jonathan Schroeder Joseph Watson Josh Wilson Julien Roland +Kai Trukenmüller Kent English Kevin C. Zimmerman +Kirill Motkov Konstantin Shaposhnikov Leonid Kneller Lyron Winderbaum +Martin Diz Matthieu Di Mercurio Max Halford MinJae Kwon +Nick Potts +Olivier Wulveryck Or Rikon Pontus Melke Renée French +Rishi Desai Robin Eklind -Samuel Kelemen Sam Zaydel +Samuel Kelemen +Saran Ahluwalia Scott Holden Sebastien Binet -source{d} Shawn Smith +source{d} Spencer Lyon Steve McCoy +Taesu Pyo Takeshi Yoneda The University of Adelaide The University of Minnesota The University of Washington +Thomas Berg Tobin Harding +Vincent Thiery Vladimír Chalupecký Yevgeniy Vahlis diff --git a/vendor/gonum.org/v1/gonum/CONTRIBUTORS b/vendor/gonum.org/v1/gonum/CONTRIBUTORS index 007d13b79d6..0c7cc46a74f 100644 --- a/vendor/gonum.org/v1/gonum/CONTRIBUTORS +++ b/vendor/gonum.org/v1/gonum/CONTRIBUTORS @@ -15,17 +15,22 @@ # # Please keep the list sorted. +Alexander Egurnov Andrew Brampton -Brendan Tracey Bill Gray Bill Noon +Brendan Tracey +Brent Pedersen Chad Kunde Chih-Wei Chang Chris Tessum +Christophe Meessen +Clayton Northey Dan Kortschak Daniel Fireman David Samborski Davor Kapsa +Dezmond Goff Egon Elbre Ekaterina Efimova Ethan Burns @@ -35,6 +40,8 @@ Fazlul Shahriar Francesc Campoy Gustaf Johansson Iakov Davydov +Igor Mikushkin +Iskander Sharipov Jalem Raj Rohit James Bell James Bowman @@ -43,31 +50,42 @@ Janne Snabb Jeff Juozapaitis Jeremy Atkinson Jonas Kahler +Jonas Schulze Jonathan J Lawlor Jonathan Schroeder Joseph Watson Josh Wilson Julien Roland +Kai Trukenmüller Kent English Kevin C. Zimmerman +Kirill Motkov Konstantin Shaposhnikov Leonid Kneller Lyron Winderbaum +Martin Diz Matthieu Di Mercurio Max Halford MinJae Kwon +Nick Potts +Olivier Wulveryck Or Rikon Pontus Melke Renée French +Rishi Desai Robin Eklind -Samuel Kelemen Sam Zaydel +Samuel Kelemen +Saran Ahluwalia Scott Holden Sebastien Binet Shawn Smith Spencer Lyon Steve McCoy +Taesu Pyo Takeshi Yoneda +Thomas Berg Tobin Harding +Vincent Thiery Vladimír Chalupecký Yevgeniy Vahlis diff --git a/vendor/gonum.org/v1/gonum/blas/BUILD b/vendor/gonum.org/v1/gonum/blas/BUILD index 0bdf7b63580..b484b19b2ee 100644 --- a/vendor/gonum.org/v1/gonum/blas/BUILD +++ b/vendor/gonum.org/v1/gonum/blas/BUILD @@ -23,6 +23,7 @@ filegroup( srcs = [ ":package-srcs", "//vendor/gonum.org/v1/gonum/blas/blas64:all-srcs", + "//vendor/gonum.org/v1/gonum/blas/cblas128:all-srcs", "//vendor/gonum.org/v1/gonum/blas/gonum:all-srcs", ], tags = ["automanaged"], diff --git a/vendor/gonum.org/v1/gonum/blas/blas.go b/vendor/gonum.org/v1/gonum/blas/blas.go index ec61c456a5f..9b933e3fc57 100644 --- a/vendor/gonum.org/v1/gonum/blas/blas.go +++ b/vendor/gonum.org/v1/gonum/blas/blas.go @@ -30,42 +30,38 @@ type DrotmParams struct { H [4]float64 // Column-major 2 by 2 matrix. } -// Transpose is used to specify the transposition operation for a -// routine. -type Transpose int +// Transpose specifies the transposition operation of a matrix. +type Transpose byte const ( - NoTrans Transpose = 111 + iota - Trans - ConjTrans + NoTrans Transpose = 'N' + Trans Transpose = 'T' + ConjTrans Transpose = 'C' ) -// Uplo is used to specify whether the matrix is an upper or lower -// triangular matrix. -type Uplo int +// Uplo specifies whether a matrix is upper or lower triangular. +type Uplo byte const ( - All Uplo = 120 + iota - Upper - Lower + Upper Uplo = 'U' + Lower Uplo = 'L' + All Uplo = 'A' ) -// Diag is used to specify whether the matrix is a unit or non-unit -// triangular matrix. -type Diag int +// Diag specifies whether a matrix is unit triangular. +type Diag byte const ( - NonUnit Diag = 131 + iota - Unit + NonUnit Diag = 'N' + Unit Diag = 'U' ) -// Side is used to specify from which side a multiplication operation -// is performed. -type Side int +// Side specifies from which side a multiplication operation is performed. +type Side byte const ( - Left Side = 141 + iota - Right + Left Side = 'L' + Right Side = 'R' ) // Float32 implements the single precision real BLAS routines. diff --git a/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go b/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go index 11dfaafb88c..551983836c5 100644 --- a/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go +++ b/vendor/gonum.org/v1/gonum/blas/blas64/blas64.go @@ -12,7 +12,8 @@ import ( var blas64 blas.Float64 = gonum.Implementation{} // Use sets the BLAS float64 implementation to be used by subsequent BLAS calls. -// The default implementation is native.Implementation. +// The default implementation is +// gonum.org/v1/gonum/blas/gonum.Implementation. func Use(b blas.Float64) { blas64 = b } @@ -27,104 +28,111 @@ func Implementation() blas.Float64 { // Vector represents a vector with an associated element increment. type Vector struct { - Inc int + N int Data []float64 + Inc int } // General represents a matrix using the conventional storage scheme. type General struct { Rows, Cols int - Stride int Data []float64 + Stride int } // Band represents a band matrix using the band storage scheme. type Band struct { Rows, Cols int KL, KU int - Stride int Data []float64 + Stride int } // 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 + N int + Data []float64 + Stride int } // 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 + N, K int + Data []float64 + Stride int } // TriangularPacked represents a triangular matrix using the packed storage scheme. type TriangularPacked struct { - N int - Data []float64 Uplo blas.Uplo Diag blas.Diag + N int + Data []float64 } // Symmetric represents a symmetric matrix using the conventional storage scheme. type Symmetric struct { - N int - Stride int - Data []float64 Uplo blas.Uplo + N int + Data []float64 + Stride int } // SymmetricBand represents a symmetric matrix using the band storage scheme. type SymmetricBand struct { - N, K int - Stride int - Data []float64 Uplo blas.Uplo + N, K int + Data []float64 + Stride int } // SymmetricPacked represents a symmetric matrix using the packed storage scheme. type SymmetricPacked struct { + Uplo blas.Uplo N int Data []float64 - Uplo blas.Uplo } // Level 1 -const negInc = "blas64: negative vector increment" +const ( + negInc = "blas64: negative vector increment" + badLength = "blas64: vector length mismatch" +) // 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) +func Dot(x, y Vector) float64 { + if x.N != y.N { + panic(badLength) + } + return blas64.Ddot(x.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 { +func Nrm2(x Vector) float64 { if x.Inc < 0 { panic(negInc) } - return blas64.Dnrm2(n, x.Data, x.Inc) + return blas64.Dnrm2(x.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 { +func Asum(x Vector) float64 { if x.Inc < 0 { panic(negInc) } - return blas64.Dasum(n, x.Data, x.Inc) + return blas64.Dasum(x.N, x.Data, x.Inc) } // Iamax returns the index of an element of x with the largest absolute value. @@ -132,29 +140,39 @@ func Asum(n int, x Vector) float64 { // Iamax returns -1 if n == 0. // // Iamax will panic if the vector increment is negative. -func Iamax(n int, x Vector) int { +func Iamax(x Vector) int { if x.Inc < 0 { panic(negInc) } - return blas64.Idamax(n, x.Data, x.Inc) + return blas64.Idamax(x.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) +func Swap(x, y Vector) { + if x.N != y.N { + panic(badLength) + } + blas64.Dswap(x.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) +// Copy requires that the lengths of x and y match and will panic otherwise. +func Copy(x, y Vector) { + if x.N != y.N { + panic(badLength) + } + blas64.Dcopy(x.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) +func Axpy(alpha float64, x, y Vector) { + if x.N != y.N { + panic(badLength) + } + blas64.Daxpy(x.N, alpha, x.Data, x.Inc, y.Data, y.Inc) } // Rotg computes the parameters of a Givens plane rotation so that @@ -184,25 +202,31 @@ func Rotmg(d1, d2, b1, b2 float64) (p blas.DrotmParams, rd1, rd2, rb1 float64) { // 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) +func Rot(x, y Vector, c, s float64) { + if x.N != y.N { + panic(badLength) + } + blas64.Drot(x.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) +func Rotm(x, y Vector, p blas.DrotmParams) { + if x.N != y.N { + panic(badLength) + } + blas64.Drotm(x.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) { +func Scal(alpha float64, x Vector) { if x.Inc < 0 { panic(negInc) } - blas64.Dscal(n, alpha, x.Data, x.Inc) + blas64.Dscal(x.N, alpha, x.Data, x.Inc) } // Level 2 diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/BUILD b/vendor/gonum.org/v1/gonum/blas/cblas128/BUILD new file mode 100644 index 00000000000..a8ab6d44ef2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/BUILD @@ -0,0 +1,33 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "cblas128.go", + "conv.go", + "conv_hermitian.go", + "conv_symmetric.go", + "doc.go", + ], + importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/blas/cblas128", + importpath = "gonum.org/v1/gonum/blas/cblas128", + visibility = ["//visibility:public"], + deps = [ + "//vendor/gonum.org/v1/gonum/blas:go_default_library", + "//vendor/gonum.org/v1/gonum/blas/gonum:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go b/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go new file mode 100644 index 00000000000..1205da8afab --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/cblas128.go @@ -0,0 +1,508 @@ +// Copyright ©2015 The Gonum Authors. 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 + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/gonum" +) + +var cblas128 blas.Complex128 = gonum.Implementation{} + +// Use sets the BLAS complex128 implementation to be used by subsequent BLAS calls. +// The default implementation is +// gonum.org/v1/gonum/blas/gonum.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/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go new file mode 100644 index 00000000000..93e3cd2f929 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv.go @@ -0,0 +1,279 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; 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 cblas128 + +import "gonum.org/v1/gonum/blas" + +// GeneralCols represents a matrix using the conventional column-major storage scheme. +type GeneralCols General + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t GeneralCols) From(a General) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if len(t.Data) < (t.Cols-1)*t.Stride+t.Rows { + panic("cblas128: short data slice") + } + for i := 0; i < a.Rows; i++ { + for j, v := range a.Data[i*a.Stride : i*a.Stride+a.Cols] { + t.Data[i+j*t.Stride] = v + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions as a and have adequate backing +// data storage. +func (t General) From(a GeneralCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if len(t.Data) < (t.Rows-1)*t.Stride+t.Cols { + panic("cblas128: short data slice") + } + for j := 0; j < a.Cols; j++ { + for i, v := range a.Data[j*a.Stride : j*a.Stride+a.Rows] { + t.Data[i*t.Stride+j] = v + } + } +} + +// TriangularCols represents a matrix using the conventional column-major storage scheme. +type TriangularCols Triangular + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t TriangularCols) From(a Triangular) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, uplo and diag as a and have +// adequate backing data storage. +func (t Triangular) From(a TriangularCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.All: + for i := 0; i < a.N; i++ { + for j := 0; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// BandCols represents a matrix using the band column-major storage scheme. +type BandCols Band + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t BandCols) From(a Band) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("cblas128: short stride for destination") + } + for i := 0; i < a.Rows; i++ { + for j := max(0, i-a.KL); j < min(i+a.KU+1, a.Cols); j++ { + t.Data[i+t.KU-j+j*t.Stride] = a.Data[j+a.KL-i+i*a.Stride] + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and bandwidth as a and have +// adequate backing data storage. +func (t Band) From(a BandCols) { + if t.Rows != a.Rows || t.Cols != a.Cols { + panic("cblas128: mismatched dimension") + } + if t.KL != a.KL || t.KU != a.KU { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.KL+a.KU+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.KL+t.KU+1 { + panic("cblas128: short stride for destination") + } + for j := 0; j < a.Cols; j++ { + for i := max(0, j-a.KU); i < min(j+a.KL+1, a.Rows); i++ { + t.Data[j+a.KL-i+i*a.Stride] = a.Data[i+t.KU-j+j*t.Stride] + } + } +} + +// TriangularBandCols represents a symmetric matrix using the band column-major storage scheme. +type TriangularBandCols TriangularBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBandCols) From(a TriangularBand) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t TriangularBand) From(a TriangularBandCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + if t.Diag != a.Diag { + panic("cblas128: mismatched BLAS diag") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +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 +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go new file mode 100644 index 00000000000..51c3a5777bb --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_hermitian.go @@ -0,0 +1,155 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; 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 cblas128 + +import "gonum.org/v1/gonum/blas" + +// HermitianCols represents a matrix using the conventional column-major storage scheme. +type HermitianCols Hermitian + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t HermitianCols) From(a Hermitian) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Hermitian) From(a HermitianCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// HermitianBandCols represents an Hermitian matrix using the band column-major storage scheme. +type HermitianBandCols HermitianBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t HermitianBandCols) From(a HermitianBand) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t HermitianBand) From(a HermitianBandCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go new file mode 100644 index 00000000000..f1bf40c2083 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/conv_symmetric.go @@ -0,0 +1,155 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas”; 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 cblas128 + +import "gonum.org/v1/gonum/blas" + +// SymmetricCols represents a matrix using the conventional column-major storage scheme. +type SymmetricCols Symmetric + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t SymmetricCols) From(a Symmetric) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i+j*t.Stride] = a.Data[i*a.Stride+j] + } + } + } +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions and uplo as a and have adequate +// backing data storage. +func (t Symmetric) From(a SymmetricCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + for i := 0; i < a.N; i++ { + for j := i; j < a.N; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + case blas.Lower: + for i := 0; i < a.N; i++ { + for j := 0; j <= i; j++ { + t.Data[i*t.Stride+j] = a.Data[i+j*a.Stride] + } + } + } +} + +// SymmetricBandCols represents a symmetric matrix using the band column-major storage scheme. +type SymmetricBandCols SymmetricBand + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBandCols) From(a SymmetricBand) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := BandCols{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := Band{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} + +// From fills the receiver with elements from a. The receiver +// must have the same dimensions, bandwidth and uplo as a and +// have adequate backing data storage. +func (t SymmetricBand) From(a SymmetricBandCols) { + if t.N != a.N { + panic("cblas128: mismatched dimension") + } + if t.K != a.K { + panic("cblas128: mismatched bandwidth") + } + if a.Stride < a.K+1 { + panic("cblas128: short stride for source") + } + if t.Stride < t.K+1 { + panic("cblas128: short stride for destination") + } + if t.Uplo != a.Uplo { + panic("cblas128: mismatched BLAS uplo") + } + dst := Band{ + Rows: t.N, Cols: t.N, + Stride: t.Stride, + Data: t.Data, + } + src := BandCols{ + Rows: a.N, Cols: a.N, + Stride: a.Stride, + Data: a.Data, + } + switch a.Uplo { + default: + panic("cblas128: bad BLAS uplo") + case blas.Upper: + dst.KU = t.K + src.KU = a.K + case blas.Lower: + dst.KL = t.K + src.KL = a.K + } + dst.From(src) +} diff --git a/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go b/vendor/gonum.org/v1/gonum/blas/cblas128/doc.go new file mode 100644 index 00000000000..09719b19e63 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/cblas128/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 cblas128 provides a simple interface to the complex128 BLAS API. +package cblas128 // import "gonum.org/v1/gonum/blas/cblas128" diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/BUILD b/vendor/gonum.org/v1/gonum/blas/gonum/BUILD index f7cd4cafac1..741399f8512 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/BUILD +++ b/vendor/gonum.org/v1/gonum/blas/gonum/BUILD @@ -3,23 +3,27 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "cmplx.go", "dgemm.go", "doc.go", + "errors.go", "gemv.go", "gonum.go", "level1cmplx128.go", - "level1double.go", - "level1double_ddot.go", - "level1single.go", - "level1single_dsdot.go", - "level1single_sdot.go", - "level1single_sdsdot.go", + "level1cmplx64.go", + "level1float32.go", + "level1float32_dsdot.go", + "level1float32_sdot.go", + "level1float32_sdsdot.go", + "level1float64.go", + "level1float64_ddot.go", "level2cmplx128.go", - "level2double.go", - "level2single.go", - "level3double.go", - "level3single.go", + "level2cmplx64.go", + "level2float32.go", + "level2float64.go", + "level3cmplx128.go", + "level3cmplx64.go", + "level3float32.go", + "level3float64.go", "sgemm.go", ], importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/blas/gonum", @@ -28,8 +32,10 @@ go_library( deps = [ "//vendor/gonum.org/v1/gonum/blas:go_default_library", "//vendor/gonum.org/v1/gonum/internal/asm/c128:go_default_library", + "//vendor/gonum.org/v1/gonum/internal/asm/c64:go_default_library", "//vendor/gonum.org/v1/gonum/internal/asm/f32:go_default_library", "//vendor/gonum.org/v1/gonum/internal/asm/f64:go_default_library", + "//vendor/gonum.org/v1/gonum/internal/cmplx64:go_default_library", "//vendor/gonum.org/v1/gonum/internal/math32:go_default_library", ], ) diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go b/vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go deleted file mode 100644 index 53180913c74..00000000000 --- a/vendor/gonum.org/v1/gonum/blas/gonum/cmplx.go +++ /dev/null @@ -1,164 +0,0 @@ -// 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 gonum - -import "gonum.org/v1/gonum/blas" - -var ( - _ blas.Complex64 = Implementation{} - _ blas.Complex128 = Implementation{} -) - -// TODO(btracey): Replace this as complex routines are added, and instead -// automatically generate the complex64 routines from the complex128 ones. - -var noComplex = "native: implementation does not implement this routine, see the cgo wrapper in gonum.org/v1/netlib/blas" - -// Level 1 complex64 routines. - -func (Implementation) Cdotu(n int, x []complex64, incX int, y []complex64, incY int) (dotu complex64) { - panic(noComplex) -} -func (Implementation) Cdotc(n int, x []complex64, incX int, y []complex64, incY int) (dotc complex64) { - panic(noComplex) -} -func (Implementation) Scnrm2(n int, x []complex64, incX int) float32 { - panic(noComplex) -} -func (Implementation) Scasum(n int, x []complex64, incX int) float32 { - panic(noComplex) -} -func (Implementation) Icamax(n int, x []complex64, incX int) int { - panic(noComplex) -} -func (Implementation) Cswap(n int, x []complex64, incX int, y []complex64, incY int) { - panic(noComplex) -} -func (Implementation) Ccopy(n int, x []complex64, incX int, y []complex64, incY int) { - panic(noComplex) -} -func (Implementation) Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) { - panic(noComplex) -} -func (Implementation) Cscal(n int, alpha complex64, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Csscal(n int, alpha float32, x []complex64, incX int) { - panic(noComplex) -} - -// Level 2 complex64 routines. - -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -func (Implementation) Ctrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Ctbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Ctpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []complex64, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Ctrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Ctbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Ctpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, ap []complex64, x []complex64, incX int) { - panic(noComplex) -} -func (Implementation) Chemv(ul blas.Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { - panic(noComplex) -} -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) { - panic(noComplex) -} -func (Implementation) Chpmv(ul blas.Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) { - panic(noComplex) -} -func (Implementation) Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { - panic(noComplex) -} -func (Implementation) Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { - panic(noComplex) -} -func (Implementation) Cher(ul blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) { - panic(noComplex) -} -func (Implementation) Chpr(ul blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64) { - panic(noComplex) -} -func (Implementation) Cher2(ul blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { - panic(noComplex) -} -func (Implementation) Chpr2(ul blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) { - panic(noComplex) -} - -// Level 3 complex64 routines. - -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -func (Implementation) Csyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) { - panic(noComplex) -} -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -func (Implementation) Cherk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) { - panic(noComplex) -} -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) { - panic(noComplex) -} - -// Level 3 complex128 routines. - -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -func (Implementation) Zsyrk(ul blas.Uplo, t blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) { - panic(noComplex) -} -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -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) { - panic(noComplex) -} -func (Implementation) Zherk(ul blas.Uplo, t blas.Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) { - panic(noComplex) -} -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) { - panic(noComplex) -} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go b/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go index 4147aa88e6f..ec3fcc61cb1 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/dgemm.go @@ -21,25 +21,81 @@ import ( // an m×n matrix, 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 { + switch tA { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + switch tB { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) } aTrans := tA == blas.Trans || tA == blas.ConjTrans if aTrans { - checkDMatrix('a', k, m, a, lda) + if lda < max(1, m) { + panic(badLdA) + } } else { - checkDMatrix('a', m, k, a, lda) + if lda < max(1, k) { + panic(badLdA) + } } bTrans := tB == blas.Trans || tB == blas.ConjTrans if bTrans { - checkDMatrix('b', n, k, b, ldb) + if ldb < max(1, k) { + panic(badLdB) + } } else { - checkDMatrix('b', k, n, b, ldb) + if ldb < max(1, n) { + panic(badLdB) + } + } + if ldc < max(1, n) { + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if aTrans { + if len(a) < (k-1)*lda+m { + panic(shortA) + } + } else { + if len(a) < (m-1)*lda+k { + panic(shortA) + } + } + if bTrans { + if len(b) < (n-1)*ldb+k { + panic(shortB) + } + } else { + if len(b) < (k-1)*ldb+n { + panic(shortB) + } + } + if len(c) < (m-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return } - checkDMatrix('c', m, n, c, ldc) // scale c if beta != 1 { @@ -124,13 +180,6 @@ func dgemmParallel(aTrans, bTrans bool, m, n, k int, a []float64, lda int, b []f wg.Add(1) go func() { defer wg.Done() - // Make local copies of otherwise global variables to reduce shared memory. - // This has a noticeable 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 @@ -210,7 +259,7 @@ func dgemmSerialNotNot(m, n, k int, a []float64, lda int, b []float64, ldb int, 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) + f64.AxpyUnitary(tmp, b[l*ldb:l*ldb+n], ctmp) } } } @@ -226,7 +275,7 @@ func dgemmSerialTransNot(m, n, k int, a []float64, lda int, b []float64, ldb int tmp := alpha * v if tmp != 0 { ctmp := c[i*ldc : i*ldc+n] - f64.AxpyUnitaryTo(ctmp, tmp, btmp, ctmp) + f64.AxpyUnitary(tmp, btmp, ctmp) } } } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/errors.go b/vendor/gonum.org/v1/gonum/blas/gonum/errors.go new file mode 100644 index 00000000000..e98575d0fa5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/errors.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 gonum + +// Panic strings used during parameter checks. +// This list is duplicated in netlib/blas/netlib. Keep in sync. +const ( + zeroIncX = "blas: zero x index increment" + zeroIncY = "blas: zero y index increment" + + 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" + badFlag = "blas: illegal rotm flag" + + badLdA = "blas: bad leading dimension of A" + badLdB = "blas: bad leading dimension of B" + badLdC = "blas: bad leading dimension of C" + + shortX = "blas: insufficient length of x" + shortY = "blas: insufficient length of y" + shortAP = "blas: insufficient length of ap" + shortA = "blas: insufficient length of a" + shortB = "blas: insufficient length of b" + shortC = "blas: insufficient length of c" +) diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/gemv.go b/vendor/gonum.org/v1/gonum/blas/gonum/gemv.go index acd8f323b83..9b9a1beb099 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/gemv.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/gemv.go @@ -29,7 +29,6 @@ func (Implementation) Dgemv(tA blas.Transpose, m, n int, alpha float64, a []floa if lda < max(1, n) { panic(badLdA) } - if incX == 0 { panic(zeroIncX) } @@ -43,18 +42,24 @@ func (Implementation) Dgemv(tA blas.Transpose, m, n int, alpha float64, a []floa lenX = n lenY = m } + + // Quick return if possible + if m == 0 || n == 0 { + return + } + if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { - panic(badX) + panic(shortX) } if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { - panic(badY) + panic(shortY) } - if lda*(m-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + if len(a) < lda*(m-1)+n { + panic(shortA) } // Quick return if possible - if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + if alpha == 0 && beta == 1 { return } @@ -96,13 +101,18 @@ func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []floa if lda < max(1, n) { panic(badLdA) } - if incX == 0 { panic(zeroIncX) } if incY == 0 { panic(zeroIncY) } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + // Set up indexes lenX := m lenY := n @@ -111,28 +121,20 @@ func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []floa lenY = m } if (incX > 0 && (lenX-1)*incX >= len(x)) || (incX < 0 && (1-lenX)*incX >= len(x)) { - panic(badX) + panic(shortX) } if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { - panic(badY) + panic(shortY) } - if lda*(m-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + if len(a) < lda*(m-1)+n { + panic(shortA) } - // Quick return if possible - if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if alpha == 0 && beta == 1 { return } - var kx, ky int - if incX < 0 { - kx = -(lenX - 1) * incX - } - if incY < 0 { - ky = -(lenY - 1) * incY - } - // First form y = beta * y if incY > 0 { Implementation{}.Sscal(lenY, beta, y, incY) @@ -144,11 +146,19 @@ func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []floa return } + var kx, ky int + if incX < 0 { + kx = -(lenX - 1) * incX + } + if incY < 0 { + ky = -(lenY - 1) * incY + } + // 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) + y[i] += alpha * f32.DotUnitary(a[lda*i:lda*i+n], x[:n]) } return } @@ -164,7 +174,7 @@ func (Implementation) Sgemv(tA blas.Transpose, m, n int, alpha float32, a []floa for i := 0; i < m; i++ { tmp := alpha * x[i] if tmp != 0 { - f32.AxpyUnitaryTo(y, tmp, a[lda*i:lda*i+n], y) + f32.AxpyUnitaryTo(y, tmp, a[lda*i:lda*i+n], y[:n]) } } return diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go b/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go index e18b69be298..8ab8d43e18e 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/gonum.go @@ -6,34 +6,14 @@ package gonum -import "math" +import ( + "math" + + "gonum.org/v1/gonum/internal/math32" +) type Implementation struct{} -// The following are panic strings used during parameter checks. -const ( - zeroIncX = "blas: zero x index increment" - zeroIncY = "blas: zero y index increment" - - 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: bad leading dimension of A" - badLdB = "blas: bad leading dimension of B" - badLdC = "blas: bad leading dimension of C" - - badX = "blas: bad length of x" - badY = "blas: bad length of y" -) - // [SD]gemm behavior constants. These are kept here to keep them out of the // way during single precision code genration. const ( @@ -61,115 +41,6 @@ func min(a, b int) int { return a } -func checkSMatrix(name byte, m, n int, a []float32, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < n { - panic("blas: illegal stride of " + string(name)) - } - if len(a) < (m-1)*lda+n { - panic("blas: index of " + string(name) + " out of range") - } -} - -func checkDMatrix(name byte, m, n int, a []float64, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < n { - panic("blas: illegal stride of " + string(name)) - } - if len(a) < (m-1)*lda+n { - panic("blas: index of " + string(name) + " out of range") - } -} - -func checkZMatrix(name byte, m, n int, a []complex128, lda int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if lda < max(1, n) { - panic("blas: illegal stride of " + string(name)) - } - if len(a) < (m-1)*lda+n { - panic("blas: insufficient " + string(name) + " matrix slice length") - } -} - -func checkZBandMatrix(name byte, m, n, kL, kU int, ab []complex128, ldab int) { - if m < 0 { - panic(mLT0) - } - if n < 0 { - panic(nLT0) - } - if kL < 0 { - panic(kLLT0) - } - if kU < 0 { - panic(kULT0) - } - if ldab < kL+kU+1 { - panic("blas: illegal stride of band matrix " + string(name)) - } - nRow := min(m, n+kL) - if len(ab) < (nRow-1)*ldab+kL+1+kU { - panic("blas: insufficient " + string(name) + " band matrix slice length") - } -} - -func checkZhbMatrix(name byte, n, k int, ab []complex128, ldab int) { - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if ldab < k+1 { - panic("blas: illegal stride of Hermitian band matrix " + string(name)) - } - if len(ab) < (n-1)*ldab+k+1 { - panic("blas: insufficient " + string(name) + " Hermitian band matrix slice length") - } -} - -func checkZtbMatrix(name byte, n, k int, ab []complex128, ldab int) { - if n < 0 { - panic(nLT0) - } - if k < 0 { - panic(kLT0) - } - if ldab < k+1 { - panic("blas: illegal stride of triangular band matrix " + string(name)) - } - if len(ab) < (n-1)*ldab+k+1 { - panic("blas: insufficient " + string(name) + " triangular band matrix slice length") - } -} - -func checkZVector(name byte, n int, x []complex128, incX int) { - 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("blas: insufficient " + string(name) + " vector slice length") - } -} - // blocks returns the number of divisions of the dimension length with the given // block size. func blocks(dim, bsize int) int { @@ -180,3 +51,8 @@ func blocks(dim, bsize int) int { func dcabs1(z complex128) float64 { return math.Abs(real(z)) + math.Abs(imag(z)) } + +// scabs1 returns |real(z)|+|imag(z)|. +func scabs1(z complex64) float32 { + return math32.Abs(real(z)) + math32.Abs(imag(z)) +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go index d437b8c8dae..e37bf44dd34 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx128.go @@ -7,9 +7,12 @@ package gonum import ( "math" + "gonum.org/v1/gonum/blas" "gonum.org/v1/gonum/internal/asm/c128" ) +var _ blas.Complex128Level1 = Implementation{} + // Dzasum returns the sum of the absolute values of the elements of x // \sum_i |Re(x[i])| + |Im(x[i])| // Dzasum returns 0 if incX is negative. @@ -26,7 +29,7 @@ func (Implementation) Dzasum(n int, x []complex128, incX int) float64 { var sum float64 if incX == 1 { if len(x) < n { - panic(badX) + panic(shortX) } for _, v := range x[:n] { sum += dcabs1(v) @@ -34,7 +37,7 @@ func (Implementation) Dzasum(n int, x []complex128, incX int) float64 { return sum } if (n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } for i := 0; i < n; i++ { v := x[i*incX] @@ -60,7 +63,7 @@ func (Implementation) Dznrm2(n int, x []complex128, incX int) float64 { panic(nLT0) } if (n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } var ( scale float64 @@ -134,7 +137,7 @@ func (Implementation) Izamax(n int, x []complex128, incX int) int { panic(nLT0) } if len(x) <= (n-1)*incX { - panic(badX) + panic(shortX) } idx := 0 max := dcabs1(x[0]) @@ -176,10 +179,10 @@ func (Implementation) Zaxpy(n int, alpha complex128, x []complex128, incX int, y panic(nLT0) } if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + panic(shortX) } if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + panic(shortY) } if alpha == 0 { return @@ -213,10 +216,10 @@ func (Implementation) Zcopy(n int, x []complex128, incX int, y []complex128, inc panic(nLT0) } if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + panic(shortX) } if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + panic(shortY) } if incX == 1 && incY == 1 { copy(y[:n], x[:n]) @@ -254,10 +257,10 @@ func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, inc } if incX == 1 && incY == 1 { if len(x) < n { - panic(badX) + panic(shortX) } if len(y) < n { - panic(badY) + panic(shortY) } return c128.DotcUnitary(x[:n], y[:n]) } @@ -269,10 +272,10 @@ func (Implementation) Zdotc(n int, x []complex128, incX int, y []complex128, inc iy = (-n + 1) * incY } if ix >= len(x) || (n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if iy >= len(y) || (n-1)*incY >= len(y) { - panic(badY) + panic(shortY) } return c128.DotcInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) } @@ -295,10 +298,10 @@ func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, inc } if incX == 1 && incY == 1 { if len(x) < n { - panic(badX) + panic(shortX) } if len(y) < n { - panic(badY) + panic(shortY) } return c128.DotuUnitary(x[:n], y[:n]) } @@ -310,10 +313,10 @@ func (Implementation) Zdotu(n int, x []complex128, incX int, y []complex128, inc iy = (-n + 1) * incY } if ix >= len(x) || (n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if iy >= len(y) || (n-1)*incY >= len(y) { - panic(badY) + panic(shortY) } return c128.DotuInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) } @@ -328,7 +331,7 @@ func (Implementation) Zdscal(n int, alpha float64, x []complex128, incX int) { return } if (n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if n < 1 { if n == 0 { @@ -372,7 +375,7 @@ func (Implementation) Zscal(n int, alpha complex128, x []complex128, incX int) { return } if (n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if n < 1 { if n == 0 { @@ -415,10 +418,10 @@ func (Implementation) Zswap(n int, x []complex128, incX int, y []complex128, inc panic(nLT0) } if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + panic(shortX) } if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + panic(shortY) } if incX == 1 && incY == 1 { x = x[:n] diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go new file mode 100644 index 00000000000..ba192ea5955 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1cmplx64.go @@ -0,0 +1,467 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// 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 gonum + +import ( + math "gonum.org/v1/gonum/internal/math32" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/c64" +) + +var _ blas.Complex64Level1 = Implementation{} + +// Scasum returns the sum of the absolute values of the elements of x +// \sum_i |Re(x[i])| + |Im(x[i])| +// Scasum returns 0 if incX is negative. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Scasum(n int, x []complex64, incX int) float32 { + if n < 0 { + panic(nLT0) + } + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + var sum float32 + if incX == 1 { + if len(x) < n { + panic(shortX) + } + for _, v := range x[:n] { + sum += scabs1(v) + } + return sum + } + if (n-1)*incX >= len(x) { + panic(shortX) + } + for i := 0; i < n; i++ { + v := x[i*incX] + sum += scabs1(v) + } + return sum +} + +// Scnrm2 computes the Euclidean norm of the complex vector x, +// ‖x‖_2 = sqrt(\sum_i x[i] * conj(x[i])). +// This function returns 0 if incX is negative. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Scnrm2(n int, x []complex64, incX int) float32 { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return 0 + } + if n < 1 { + if n == 0 { + return 0 + } + panic(nLT0) + } + if (n-1)*incX >= len(x) { + panic(shortX) + } + var ( + scale float32 + ssq float32 = 1 + ) + if incX == 1 { + for _, v := range x[:n] { + re, im := math.Abs(real(v)), math.Abs(imag(v)) + if re != 0 { + if re > scale { + ssq = 1 + ssq*(scale/re)*(scale/re) + scale = re + } else { + ssq += (re / scale) * (re / scale) + } + } + if im != 0 { + if im > scale { + ssq = 1 + ssq*(scale/im)*(scale/im) + scale = im + } else { + ssq += (im / scale) * (im / scale) + } + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(ssq) + } + for ix := 0; ix < n*incX; ix += incX { + re, im := math.Abs(real(x[ix])), math.Abs(imag(x[ix])) + if re != 0 { + if re > scale { + ssq = 1 + ssq*(scale/re)*(scale/re) + scale = re + } else { + ssq += (re / scale) * (re / scale) + } + } + if im != 0 { + if im > scale { + ssq = 1 + ssq*(scale/im)*(scale/im) + scale = im + } else { + ssq += (im / scale) * (im / scale) + } + } + } + if math.IsInf(scale, 1) { + return math.Inf(1) + } + return scale * math.Sqrt(ssq) +} + +// Icamax returns the index of the first element of x having largest |Re(·)|+|Im(·)|. +// Icamax returns -1 if n is 0 or incX is negative. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Icamax(n int, x []complex64, incX int) int { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + // Return invalid index. + return -1 + } + if n < 1 { + if n == 0 { + // Return invalid index. + return -1 + } + panic(nLT0) + } + if len(x) <= (n-1)*incX { + panic(shortX) + } + idx := 0 + max := scabs1(x[0]) + if incX == 1 { + for i, v := range x[1:n] { + absV := scabs1(v) + if absV > max { + max = absV + idx = i + 1 + } + } + return idx + } + ix := incX + for i := 1; i < n; i++ { + absV := scabs1(x[ix]) + if absV > max { + max = absV + idx = i + } + ix += incX + } + return idx +} + +// Caxpy adds alpha times x to y: +// y[i] += alpha * x[i] for all i +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Caxpy(n int, alpha complex64, x []complex64, incX int, y []complex64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(nLT0) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(shortX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(shortY) + } + if alpha == 0 { + return + } + if incX == 1 && incY == 1 { + c64.AxpyUnitary(alpha, x[:n], y[:n]) + return + } + var ix, iy int + if incX < 0 { + ix = (1 - n) * incX + } + if incY < 0 { + iy = (1 - n) * incY + } + c64.AxpyInc(alpha, x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Ccopy copies the vector x to vector y. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ccopy(n int, x []complex64, incX int, y []complex64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(nLT0) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(shortX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(shortY) + } + 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 + } +} + +// Cdotc computes the dot product +// x^H · y +// of two complex vectors x and y. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cdotc(n int, x []complex64, incX int, y []complex64, incY int) complex64 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(nLT0) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(shortX) + } + if len(y) < n { + panic(shortY) + } + return c64.DotcUnitary(x[:n], y[:n]) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || (n-1)*incX >= len(x) { + panic(shortX) + } + if iy >= len(y) || (n-1)*incY >= len(y) { + panic(shortY) + } + return c64.DotcInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Cdotu computes the dot product +// x^T · y +// of two complex vectors x and y. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cdotu(n int, x []complex64, incX int, y []complex64, incY int) complex64 { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n <= 0 { + if n == 0 { + return 0 + } + panic(nLT0) + } + if incX == 1 && incY == 1 { + if len(x) < n { + panic(shortX) + } + if len(y) < n { + panic(shortY) + } + return c64.DotuUnitary(x[:n], y[:n]) + } + var ix, iy int + if incX < 0 { + ix = (-n + 1) * incX + } + if incY < 0 { + iy = (-n + 1) * incY + } + if ix >= len(x) || (n-1)*incX >= len(x) { + panic(shortX) + } + if iy >= len(y) || (n-1)*incY >= len(y) { + panic(shortY) + } + return c64.DotuInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) +} + +// Csscal scales the vector x by a real scalar alpha. +// Csscal has no effect if incX < 0. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Csscal(n int, alpha float32, x []complex64, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(shortX) + } + if n < 1 { + if n == 0 { + return + } + panic(nLT0) + } + 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 { + x = x[:n] + for i, v := range x { + x[i] = complex(alpha*real(v), alpha*imag(v)) + } + return + } + for ix := 0; ix < n*incX; ix += incX { + v := x[ix] + x[ix] = complex(alpha*real(v), alpha*imag(v)) + } +} + +// Cscal scales the vector x by a complex scalar alpha. +// Cscal has no effect if incX < 0. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cscal(n int, alpha complex64, x []complex64, incX int) { + if incX < 1 { + if incX == 0 { + panic(zeroIncX) + } + return + } + if (n-1)*incX >= len(x) { + panic(shortX) + } + if n < 1 { + if n == 0 { + return + } + panic(nLT0) + } + 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 { + c64.ScalUnitary(alpha, x[:n]) + return + } + c64.ScalInc(alpha, x, uintptr(n), uintptr(incX)) +} + +// Cswap exchanges the elements of two complex vectors x and y. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cswap(n int, x []complex64, incX int, y []complex64, incY int) { + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + if n < 1 { + if n == 0 { + return + } + panic(nLT0) + } + if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { + panic(shortX) + } + if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { + panic(shortY) + } + 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 + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go similarity index 89% rename from vendor/gonum.org/v1/gonum/blas/gonum/level1single.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go index c34cd943241..ee82083a6b9 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1single.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32.go @@ -27,8 +27,8 @@ func (Implementation) Snrm2(n int, x []float32, incX int) float32 { } return 0 } - if incX > 0 && (n-1)*incX >= len(x) { - panic(badX) + if len(x) <= (n-1)*incX { + panic(shortX) } if n < 2 { if n == 1 { @@ -103,8 +103,8 @@ func (Implementation) Sasum(n int, x []float32, incX int) float32 { } return 0 } - if incX > 0 && (n-1)*incX >= len(x) { - panic(badX) + if len(x) <= (n-1)*incX { + panic(shortX) } if incX == 1 { x = x[:n] @@ -131,15 +131,15 @@ func (Implementation) Isamax(n int, x []float32, incX int) int { } return -1 } - if incX > 0 && (n-1)*incX >= len(x) { - panic(badX) + if len(x) <= (n-1)*incX { + panic(shortX) } if n < 2 { if n == 1 { return 0 } if n == 0 { - return -1 // Netlib returns invalid index when n == 0 + return -1 // Netlib returns invalid index when n == 0. } panic(nLT0) } @@ -185,11 +185,11 @@ func (Implementation) Sswap(n int, x []float32, incX int, y []float32, incY int) } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if incX == 1 && incY == 1 { x = x[:n] @@ -229,11 +229,11 @@ func (Implementation) Scopy(n int, x []float32, incX int, y []float32, incY int) } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if incX == 1 && incY == 1 { copy(y[:n], x[:n]) @@ -270,11 +270,11 @@ func (Implementation) Saxpy(n int, alpha float32, x []float32, incX int, y []flo } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if alpha == 0 { return @@ -303,7 +303,7 @@ func (Implementation) Saxpy(n int, alpha float32, x []float32, incX int, y []flo // 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 +// NOTE: There is a discrepancy between the reference 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. @@ -440,7 +440,7 @@ func (Implementation) Srotmg(d1, d2, x1, y1 float32) (p blas.SrotmParams, rd1, r case blas.Rescaling: p.H = [4]float32{h11, h21, h12, h22} default: - panic("blas: unexpected blas.Flag") + panic(badFlag) } return p, d1, d2, x1 @@ -464,11 +464,11 @@ func (Implementation) Srot(n int, x []float32, incX int, y []float32, incY int, } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if incX == 1 && incY == 1 { x = x[:n] @@ -510,11 +510,11 @@ func (Implementation) Srotm(n int, x []float32, incX int, y []float32, incY int, } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if p.Flag == blas.Identity { @@ -614,15 +614,15 @@ func (Implementation) Sscal(n int, alpha float32, x []float32, incX int) { } return } - if (n-1)*incX >= len(x) { - panic(badX) - } if n < 1 { if n == 0 { return } panic(nLT0) } + if (n-1)*incX >= len(x) { + panic(shortX) + } if alpha == 0 { if incX == 1 { x = x[:n] diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go similarity index 90% rename from vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go index 3c9ef12270a..089e0d8f0d6 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_dsdot.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_dsdot.go @@ -29,12 +29,12 @@ func (Implementation) Dsdot(n int, x []float32, incX int, y []float32, incY int) } if incX == 1 && incY == 1 { if len(x) < n { - panic(badX) + panic(shortX) } if len(y) < n { - panic(badY) + panic(shortY) } - return f32.DdotUnitary(x[:n], y) + return f32.DdotUnitary(x[:n], y[:n]) } var ix, iy int if incX < 0 { @@ -44,10 +44,10 @@ func (Implementation) Dsdot(n int, x []float32, incX int, y []float32, incY int) iy = (-n + 1) * incY } if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(badY) + panic(shortY) } return f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go similarity index 90% rename from vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go index 72fe6f8146b..41c3e792391 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdot.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdot.go @@ -29,12 +29,12 @@ func (Implementation) Sdot(n int, x []float32, incX int, y []float32, incY int) } if incX == 1 && incY == 1 { if len(x) < n { - panic(badX) + panic(shortX) } if len(y) < n { - panic(badY) + panic(shortY) } - return f32.DotUnitary(x[:n], y) + return f32.DotUnitary(x[:n], y[:n]) } var ix, iy int if incX < 0 { @@ -44,10 +44,10 @@ func (Implementation) Sdot(n int, x []float32, incX int, y []float32, incY int) iy = (-n + 1) * incY } if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(badY) + panic(shortY) } return f32.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go similarity index 90% rename from vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go index 81142c48346..69dd8aa1f00 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1single_sdsdot.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1float32_sdsdot.go @@ -29,12 +29,12 @@ func (Implementation) Sdsdot(n int, alpha float32, x []float32, incX int, y []fl } if incX == 1 && incY == 1 { if len(x) < n { - panic(badX) + panic(shortX) } if len(y) < n { - panic(badY) + panic(shortY) } - return alpha + float32(f32.DdotUnitary(x[:n], y)) + return alpha + float32(f32.DdotUnitary(x[:n], y[:n])) } var ix, iy int if incX < 0 { @@ -44,10 +44,10 @@ func (Implementation) Sdsdot(n int, alpha float32, x []float32, incX int, y []fl iy = (-n + 1) * incY } if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(badY) + panic(shortY) } return alpha + float32(f32.DdotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy))) } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1double.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go similarity index 89% rename from vendor/gonum.org/v1/gonum/blas/gonum/level1double.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go index 84a6f2b0625..2e8ed543a35 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1double.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1float64.go @@ -23,8 +23,8 @@ func (Implementation) Dnrm2(n int, x []float64, incX int) float64 { } return 0 } - if incX > 0 && (n-1)*incX >= len(x) { - panic(badX) + if len(x) <= (n-1)*incX { + panic(shortX) } if n < 2 { if n == 1 { @@ -97,8 +97,8 @@ func (Implementation) Dasum(n int, x []float64, incX int) float64 { } return 0 } - if incX > 0 && (n-1)*incX >= len(x) { - panic(badX) + if len(x) <= (n-1)*incX { + panic(shortX) } if incX == 1 { x = x[:n] @@ -123,15 +123,15 @@ func (Implementation) Idamax(n int, x []float64, incX int) int { } return -1 } - if incX > 0 && (n-1)*incX >= len(x) { - panic(badX) + if len(x) <= (n-1)*incX { + panic(shortX) } if n < 2 { if n == 1 { return 0 } if n == 0 { - return -1 // Netlib returns invalid index when n == 0 + return -1 // Netlib returns invalid index when n == 0. } panic(nLT0) } @@ -175,11 +175,11 @@ func (Implementation) Dswap(n int, x []float64, incX int, y []float64, incY int) } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if incX == 1 && incY == 1 { x = x[:n] @@ -217,11 +217,11 @@ func (Implementation) Dcopy(n int, x []float64, incX int, y []float64, incY int) } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if incX == 1 && incY == 1 { copy(y[:n], x[:n]) @@ -256,11 +256,11 @@ func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []flo } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if alpha == 0 { return @@ -289,7 +289,7 @@ func (Implementation) Daxpy(n int, alpha float64, x []float64, incX int, y []flo // 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 +// NOTE: There is a discrepancy between the reference 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. @@ -422,7 +422,7 @@ func (Implementation) Drotmg(d1, d2, x1, y1 float64) (p blas.DrotmParams, rd1, r case blas.Rescaling: p.H = [4]float64{h11, h21, h12, h22} default: - panic("blas: unexpected blas.Flag") + panic(badFlag) } return p, d1, d2, x1 @@ -444,11 +444,11 @@ func (Implementation) Drot(n int, x []float64, incX int, y []float64, incY int, } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if incX == 1 && incY == 1 { x = x[:n] @@ -488,11 +488,11 @@ func (Implementation) Drotm(n int, x []float64, incX int, y []float64, incY int, } panic(nLT0) } - if (incX > 0 && (n-1)*incX >= len(x)) || (incX < 0 && (1-n)*incX >= len(x)) { - panic(badX) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } if p.Flag == blas.Identity { @@ -590,15 +590,15 @@ func (Implementation) Dscal(n int, alpha float64, x []float64, incX int) { } return } - if (n-1)*incX >= len(x) { - panic(badX) - } if n < 1 { if n == 0 { return } panic(nLT0) } + if (n-1)*incX >= len(x) { + panic(shortX) + } if alpha == 0 { if incX == 1 { x = x[:n] diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go b/vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go similarity index 89% rename from vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go index 95205e75490..be87ba13db7 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level1double_ddot.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level1float64_ddot.go @@ -25,12 +25,12 @@ func (Implementation) Ddot(n int, x []float64, incX int, y []float64, incY int) } if incX == 1 && incY == 1 { if len(x) < n { - panic(badX) + panic(shortX) } if len(y) < n { - panic(badY) + panic(shortY) } - return f64.DotUnitary(x[:n], y) + return f64.DotUnitary(x[:n], y[:n]) } var ix, iy int if incX < 0 { @@ -40,10 +40,10 @@ func (Implementation) Ddot(n int, x []float64, incX int, y []float64, incY int) iy = (-n + 1) * incY } if ix >= len(x) || ix+(n-1)*incX >= len(x) { - panic(badX) + panic(shortX) } if iy >= len(y) || iy+(n-1)*incY >= len(y) { - panic(badY) + panic(shortY) } return f64.DotInc(x, y, uintptr(n), uintptr(incX), uintptr(incY), uintptr(ix), uintptr(iy)) } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go index 6af2a5ba7c5..03ee328fdba 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx128.go @@ -11,29 +11,66 @@ import ( "gonum.org/v1/gonum/internal/asm/c128" ) +var _ blas.Complex128Level2 = Implementation{} + // Zgbmv performs one of the matrix-vector operations // y = alpha * A * x + beta * y if trans = blas.NoTrans // y = alpha * A^T * x + beta * y if trans = blas.Trans // y = alpha * A^H * x + beta * y if trans = blas.ConjTrans // where alpha and beta are scalars, x and y are vectors, and A is an m×n band matrix // with kL sub-diagonals and kU super-diagonals. -func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha complex128, ab []complex128, ldab int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - checkZBandMatrix('A', m, n, kL, kU, ab, ldab) - var lenX, lenY int +func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { switch trans { default: panic(badTranspose) - case blas.NoTrans: - lenX = n - lenY = m - case blas.Trans, blas.ConjTrans: - lenX = m - lenY = n + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if kL < 0 { + panic(kLLT0) + } + if kU < 0 { + panic(kULT0) + } + if lda < kL+kU+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) } - checkZVector('x', lenX, x, incX) - checkZVector('y', lenY, y, incY) - if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { + panic(shortA) + } + var lenX, lenY int + if trans == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -82,7 +119,7 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple for i := 0; i < nRow; i++ { l := max(0, kL-i) u := min(nCol, n+kL-i) - aRow := ab[i*ldab+l : i*ldab+u] + aRow := a[i*lda+l : i*lda+u] off := max(0, i-kL) xtmp := x[off : off+u-l] var sum complex128 @@ -96,7 +133,7 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple for i := 0; i < nRow; i++ { l := max(0, kL-i) u := min(nCol, n+kL-i) - aRow := ab[i*ldab+l : i*ldab+u] + aRow := a[i*lda+l : i*lda+u] off := max(0, i-kL) * incX jx := kx var sum complex128 @@ -113,7 +150,7 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple for i := 0; i < nRow; i++ { l := max(0, kL-i) u := min(nCol, n+kL-i) - aRow := ab[i*ldab+l : i*ldab+u] + aRow := a[i*lda+l : i*lda+u] off := max(0, i-kL) * incY alphaxi := alpha * x[i] jy := ky @@ -127,7 +164,7 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple for i := 0; i < nRow; i++ { l := max(0, kL-i) u := min(nCol, n+kL-i) - aRow := ab[i*ldab+l : i*ldab+u] + aRow := a[i*lda+l : i*lda+u] off := max(0, i-kL) * incY alphaxi := alpha * x[ix] jy := ky @@ -143,7 +180,7 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple for i := 0; i < nRow; i++ { l := max(0, kL-i) u := min(nCol, n+kL-i) - aRow := ab[i*ldab+l : i*ldab+u] + aRow := a[i*lda+l : i*lda+u] off := max(0, i-kL) * incY alphaxi := alpha * x[i] jy := ky @@ -157,7 +194,7 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple for i := 0; i < nRow; i++ { l := max(0, kL-i) u := min(nCol, n+kL-i) - aRow := ab[i*ldab+l : i*ldab+u] + aRow := a[i*lda+l : i*lda+u] off := max(0, i-kL) * incY alphaxi := alpha * x[ix] jy := ky @@ -177,22 +214,33 @@ func (Implementation) Zgbmv(trans blas.Transpose, m, n, kL, kU int, alpha comple // y = alpha * A^H * x + beta * y if trans = blas.ConjTrans // where alpha and beta are scalars, x and y are vectors, and A is an m×n dense matrix. func (Implementation) Zgemv(trans blas.Transpose, m, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - checkZMatrix('A', m, n, a, lda) switch trans { default: panic(badTranspose) - case blas.NoTrans: - checkZVector('x', n, x, incX) - checkZVector('y', m, y, incY) - case blas.Trans, blas.ConjTrans: - checkZVector('x', m, x, incX) - checkZVector('y', n, y, incY) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + 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) } - if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if m == 0 || n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. var lenX, lenY int if trans == blas.NoTrans { lenX = n @@ -201,6 +249,21 @@ func (Implementation) Zgemv(trans blas.Transpose, m, n int, alpha complex128, a lenX = m lenY = n } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + var kx int if incX < 0 { kx = (1 - lenX) * incX @@ -305,11 +368,40 @@ func (Implementation) Zgemv(trans blas.Transpose, m, n int, alpha complex128, a // where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, // and y is an n element vector. func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { - checkZMatrix('A', m, n, a, lda) - checkZVector('x', m, x, incX) - checkZVector('y', n, y, incY) + 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) + } - if m == 0 || n == 0 || alpha == 0 { + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -334,11 +426,40 @@ func (Implementation) Zgerc(m, n int, alpha complex128, x []complex128, incX int // where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, // and y is an n element vector. func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { - checkZMatrix('A', m, n, a, lda) - checkZVector('x', m, x, incX) - checkZVector('y', n, y, incY) + 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) + } - if m == 0 || n == 0 || alpha == 0 { + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -374,15 +495,46 @@ func (Implementation) Zgeru(m, n int, alpha complex128, x []complex128, incX int // where alpha and beta are scalars, x and y are vectors, and A is an n×n // Hermitian band matrix with k super-diagonals. The imaginary parts of // the diagonal elements of A are ignored and assumed to be zero. -func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, ab []complex128, ldab int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - if uplo != blas.Upper && uplo != blas.Lower { +func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) } - checkZhbMatrix('A', n, k, ab, ldab) - checkZVector('x', n, x, incX) - checkZVector('y', n, y, incY) - if n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -428,13 +580,13 @@ func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, ab []com return } - // The elements of A are accessed sequentially with one pass through ab. + // The elements of A are accessed sequentially with one pass through a. switch uplo { case blas.Upper: iy := ky if incX == 1 { for i := 0; i < n; i++ { - aRow := ab[i*ldab:] + aRow := a[i*lda:] alphaxi := alpha * x[i] sum := alphaxi * complex(real(aRow[0]), 0) u := min(k+1, n-i) @@ -451,7 +603,7 @@ func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, ab []com } else { ix := kx for i := 0; i < n; i++ { - aRow := ab[i*ldab:] + aRow := a[i*lda:] alphaxi := alpha * x[ix] sum := alphaxi * complex(real(aRow[0]), 0) u := min(k+1, n-i) @@ -476,7 +628,7 @@ func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, ab []com l := max(0, k-i) alphaxi := alpha * x[i] jy := l * incY - aRow := ab[i*ldab:] + aRow := a[i*lda:] for j := l; j < k; j++ { v := aRow[j] y[iy] += alpha * v * x[i-k+j] @@ -493,7 +645,7 @@ func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, ab []com alphaxi := alpha * x[ix] jx := l * incX jy := l * incY - aRow := ab[i*ldab:] + aRow := a[i*lda:] for j := l; j < k; j++ { v := aRow[j] y[iy] += alpha * v * x[ix-k*incX+jx] @@ -515,14 +667,42 @@ func (Implementation) Zhbmv(uplo blas.Uplo, n, k int, alpha complex128, ab []com // Hermitian matrix. The imaginary parts of the diagonal elements of A are // ignored and assumed to be zero. func (Implementation) Zhemv(uplo blas.Uplo, n int, alpha complex128, a []complex128, lda int, x []complex128, incX int, beta complex128, y []complex128, incY int) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) } - checkZMatrix('A', n, n, a, lda) - checkZVector('x', n, x, incX) - checkZVector('y', n, y, incY) - if n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -647,13 +827,36 @@ func (Implementation) Zhemv(uplo blas.Uplo, n int, alpha complex128, a []complex // element vector. On entry, the imaginary parts of the diagonal elements of A // are ignored and assumed to be zero, on return they will be set to zero. func (Implementation) Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, a []complex128, lda int) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) } - checkZMatrix('A', n, n, a, lda) - checkZVector('x', n, x, incX) - if n == 0 || alpha == 0 { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -746,14 +949,42 @@ func (Implementation) Zher(uplo blas.Uplo, n int, alpha float64, x []complex128, // Hermitian matrix. On entry, the imaginary parts of the diagonal elements are // ignored and assumed to be zero. On return they will be set to zero. func (Implementation) Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, a []complex128, lda int) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) } - checkZMatrix('A', n, n, a, lda) - checkZVector('x', n, x, incX) - checkZVector('y', n, y, incY) - if n == 0 || alpha == 0 { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -855,16 +1086,39 @@ func (Implementation) Zher2(uplo blas.Uplo, n int, alpha complex128, x []complex // Hermitian matrix in packed form. The imaginary parts of the diagonal // elements of A are ignored and assumed to be zero. func (Implementation) Zhpmv(uplo blas.Uplo, n int, alpha complex128, ap []complex128, x []complex128, incX int, beta complex128, y []complex128, incY int) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: } - checkZVector('x', n, x, incX) - checkZVector('y', n, y, incY) - if len(ap) < n*(n+1)/2 { - panic("blas: insufficient A packed matrix slice length") + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) } - if n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -999,18 +1253,33 @@ func (Implementation) Zhpmv(uplo blas.Uplo, n int, alpha complex128, ap []comple // in packed form. On entry, the imaginary parts of the diagonal elements are // assumed to be zero, and on return they are set to zero. func (Implementation) Zhpr(uplo blas.Uplo, n int, alpha float64, x []complex128, incX int, ap []complex128) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: } if n < 0 { panic(nLT0) } - checkZVector('x', n, x, incX) - if len(ap) < n*(n+1)/2 { - panic("blas: insufficient A packed matrix slice length") + if incX == 0 { + panic(zeroIncX) } - if n == 0 || alpha == 0 { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -1118,19 +1387,39 @@ func (Implementation) Zhpr(uplo blas.Uplo, n int, alpha float64, x []complex128, // n×n Hermitian matrix, supplied in packed form. On entry, the imaginary parts // of the diagonal elements are assumed to be zero, and on return they are set to zero. func (Implementation) Zhpr2(uplo blas.Uplo, n int, alpha complex128, x []complex128, incX int, y []complex128, incY int, ap []complex128) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: } if n < 0 { panic(nLT0) } - checkZVector('x', n, x, incX) - checkZVector('y', n, y, incY) - if len(ap) < n*(n+1)/2 { - panic("blas: insufficient A packed matrix slice length") + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) } - if n == 0 || alpha == 0 { + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -1245,23 +1534,48 @@ func (Implementation) Zhpr2(uplo blas.Uplo, n int, alpha complex128, x []complex // x = A^H * x if trans = blas.ConjTrans // where x is an n element vector and A is an n×n triangular band matrix, with // (k+1) diagonals. -func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, ab []complex128, ldab int, x []complex128, incX int) { - if uplo != blas.Upper && uplo != blas.Lower { - panic(badUplo) - } - if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans { +func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { + switch trans { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if diag != blas.Unit && diag != blas.NonUnit { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) } - checkZtbMatrix('A', n, k, ab, ldab) - checkZVector('x', n, x, incX) + // Quick return if possible. if n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + // Set up start index in X. var kx int if incX < 0 { @@ -1275,10 +1589,10 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := 0; i < n; i++ { xi := x[i] if diag == blas.NonUnit { - xi *= ab[i*ldab] + xi *= a[i*lda] } kk := min(k, n-i-1) - for j, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for j, aij := range a[i*lda+1 : i*lda+kk+1] { xi += x[i+j+1] * aij } x[i] = xi @@ -1288,11 +1602,11 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := 0; i < n; i++ { xi := x[ix] if diag == blas.NonUnit { - xi *= ab[i*ldab] + xi *= a[i*lda] } kk := min(k, n-i-1) jx := ix + incX - for _, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for _, aij := range a[i*lda+1 : i*lda+kk+1] { xi += x[jx] * aij jx += incX } @@ -1305,10 +1619,10 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := n - 1; i >= 0; i-- { xi := x[i] if diag == blas.NonUnit { - xi *= ab[i*ldab+k] + xi *= a[i*lda+k] } kk := min(k, i) - for j, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for j, aij := range a[i*lda+k-kk : i*lda+k] { xi += x[i-kk+j] * aij } x[i] = xi @@ -1318,11 +1632,11 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := n - 1; i >= 0; i-- { xi := x[ix] if diag == blas.NonUnit { - xi *= ab[i*ldab+k] + xi *= a[i*lda+k] } kk := min(k, i) jx := ix - kk*incX - for _, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for _, aij := range a[i*lda+k-kk : i*lda+k] { xi += x[jx] * aij jx += incX } @@ -1337,11 +1651,11 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := n - 1; i >= 0; i-- { kk := min(k, n-i-1) xi := x[i] - for j, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for j, aij := range a[i*lda+1 : i*lda+kk+1] { x[i+j+1] += xi * aij } if diag == blas.NonUnit { - x[i] *= ab[i*ldab] + x[i] *= a[i*lda] } } } else { @@ -1350,12 +1664,12 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag kk := min(k, n-i-1) jx := ix + incX xi := x[ix] - for _, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for _, aij := range a[i*lda+1 : i*lda+kk+1] { x[jx] += xi * aij jx += incX } if diag == blas.NonUnit { - x[ix] *= ab[i*ldab] + x[ix] *= a[i*lda] } ix -= incX } @@ -1365,11 +1679,11 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := 0; i < n; i++ { kk := min(k, i) xi := x[i] - for j, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for j, aij := range a[i*lda+k-kk : i*lda+k] { x[i-kk+j] += xi * aij } if diag == blas.NonUnit { - x[i] *= ab[i*ldab+k] + x[i] *= a[i*lda+k] } } } else { @@ -1378,12 +1692,12 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag kk := min(k, i) jx := ix - kk*incX xi := x[ix] - for _, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for _, aij := range a[i*lda+k-kk : i*lda+k] { x[jx] += xi * aij jx += incX } if diag == blas.NonUnit { - x[ix] *= ab[i*ldab+k] + x[ix] *= a[i*lda+k] } ix += incX } @@ -1395,11 +1709,11 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := n - 1; i >= 0; i-- { kk := min(k, n-i-1) xi := x[i] - for j, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for j, aij := range a[i*lda+1 : i*lda+kk+1] { x[i+j+1] += xi * cmplx.Conj(aij) } if diag == blas.NonUnit { - x[i] *= cmplx.Conj(ab[i*ldab]) + x[i] *= cmplx.Conj(a[i*lda]) } } } else { @@ -1408,12 +1722,12 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag kk := min(k, n-i-1) jx := ix + incX xi := x[ix] - for _, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for _, aij := range a[i*lda+1 : i*lda+kk+1] { x[jx] += xi * cmplx.Conj(aij) jx += incX } if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(ab[i*ldab]) + x[ix] *= cmplx.Conj(a[i*lda]) } ix -= incX } @@ -1423,11 +1737,11 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := 0; i < n; i++ { kk := min(k, i) xi := x[i] - for j, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for j, aij := range a[i*lda+k-kk : i*lda+k] { x[i-kk+j] += xi * cmplx.Conj(aij) } if diag == blas.NonUnit { - x[i] *= cmplx.Conj(ab[i*ldab+k]) + x[i] *= cmplx.Conj(a[i*lda+k]) } } } else { @@ -1436,12 +1750,12 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag kk := min(k, i) jx := ix - kk*incX xi := x[ix] - for _, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for _, aij := range a[i*lda+k-kk : i*lda+k] { x[jx] += xi * cmplx.Conj(aij) jx += incX } if diag == blas.NonUnit { - x[ix] *= cmplx.Conj(ab[i*ldab+k]) + x[ix] *= cmplx.Conj(a[i*lda+k]) } ix += incX } @@ -1462,23 +1776,48 @@ func (Implementation) Ztbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag // // No test for singularity or near-singularity is included in this // routine. Such tests must be performed before calling this routine. -func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, ab []complex128, ldab int, x []complex128, incX int) { - if uplo != blas.Upper && uplo != blas.Lower { - panic(badUplo) - } - if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans { +func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex128, lda int, x []complex128, incX int) { + switch trans { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if diag != blas.Unit && diag != blas.NonUnit { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) } - checkZtbMatrix('A', n, k, ab, ldab) - checkZVector('x', n, x, incX) + // Quick return if possible. if n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + // Set up start index in X. var kx int if incX < 0 { @@ -1492,12 +1831,12 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := n - 1; i >= 0; i-- { kk := min(k, n-i-1) var sum complex128 - for j, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for j, aij := range a[i*lda+1 : i*lda+kk+1] { sum += x[i+1+j] * aij } x[i] -= sum if diag == blas.NonUnit { - x[i] /= ab[i*ldab] + x[i] /= a[i*lda] } } } else { @@ -1506,13 +1845,13 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag kk := min(k, n-i-1) var sum complex128 jx := ix + incX - for _, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for _, aij := range a[i*lda+1 : i*lda+kk+1] { sum += x[jx] * aij jx += incX } x[ix] -= sum if diag == blas.NonUnit { - x[ix] /= ab[i*ldab] + x[ix] /= a[i*lda] } ix -= incX } @@ -1522,12 +1861,12 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag for i := 0; i < n; i++ { kk := min(k, i) var sum complex128 - for j, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for j, aij := range a[i*lda+k-kk : i*lda+k] { sum += x[i-kk+j] * aij } x[i] -= sum if diag == blas.NonUnit { - x[i] /= ab[i*ldab+k] + x[i] /= a[i*lda+k] } } } else { @@ -1536,13 +1875,13 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag kk := min(k, i) var sum complex128 jx := ix - kk*incX - for _, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for _, aij := range a[i*lda+k-kk : i*lda+k] { sum += x[jx] * aij jx += incX } x[ix] -= sum if diag == blas.NonUnit { - x[ix] /= ab[i*ldab+k] + x[ix] /= a[i*lda+k] } ix += incX } @@ -1553,11 +1892,11 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag if incX == 1 { for i := 0; i < n; i++ { if diag == blas.NonUnit { - x[i] /= ab[i*ldab] + x[i] /= a[i*lda] } kk := min(k, n-i-1) xi := x[i] - for j, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for j, aij := range a[i*lda+1 : i*lda+kk+1] { x[i+1+j] -= xi * aij } } @@ -1565,12 +1904,12 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag ix := kx for i := 0; i < n; i++ { if diag == blas.NonUnit { - x[ix] /= ab[i*ldab] + x[ix] /= a[i*lda] } kk := min(k, n-i-1) xi := x[ix] jx := ix + incX - for _, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for _, aij := range a[i*lda+1 : i*lda+kk+1] { x[jx] -= xi * aij jx += incX } @@ -1581,11 +1920,11 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag if incX == 1 { for i := n - 1; i >= 0; i-- { if diag == blas.NonUnit { - x[i] /= ab[i*ldab+k] + x[i] /= a[i*lda+k] } kk := min(k, i) xi := x[i] - for j, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for j, aij := range a[i*lda+k-kk : i*lda+k] { x[i-kk+j] -= xi * aij } } @@ -1593,12 +1932,12 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag ix := kx + (n-1)*incX for i := n - 1; i >= 0; i-- { if diag == blas.NonUnit { - x[ix] /= ab[i*ldab+k] + x[ix] /= a[i*lda+k] } kk := min(k, i) xi := x[ix] jx := ix - kk*incX - for _, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for _, aij := range a[i*lda+k-kk : i*lda+k] { x[jx] -= xi * aij jx += incX } @@ -1611,11 +1950,11 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag if incX == 1 { for i := 0; i < n; i++ { if diag == blas.NonUnit { - x[i] /= cmplx.Conj(ab[i*ldab]) + x[i] /= cmplx.Conj(a[i*lda]) } kk := min(k, n-i-1) xi := x[i] - for j, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for j, aij := range a[i*lda+1 : i*lda+kk+1] { x[i+1+j] -= xi * cmplx.Conj(aij) } } @@ -1623,12 +1962,12 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag ix := kx for i := 0; i < n; i++ { if diag == blas.NonUnit { - x[ix] /= cmplx.Conj(ab[i*ldab]) + x[ix] /= cmplx.Conj(a[i*lda]) } kk := min(k, n-i-1) xi := x[ix] jx := ix + incX - for _, aij := range ab[i*ldab+1 : i*ldab+kk+1] { + for _, aij := range a[i*lda+1 : i*lda+kk+1] { x[jx] -= xi * cmplx.Conj(aij) jx += incX } @@ -1639,11 +1978,11 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag if incX == 1 { for i := n - 1; i >= 0; i-- { if diag == blas.NonUnit { - x[i] /= cmplx.Conj(ab[i*ldab+k]) + x[i] /= cmplx.Conj(a[i*lda+k]) } kk := min(k, i) xi := x[i] - for j, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for j, aij := range a[i*lda+k-kk : i*lda+k] { x[i-kk+j] -= xi * cmplx.Conj(aij) } } @@ -1651,12 +1990,12 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag ix := kx + (n-1)*incX for i := n - 1; i >= 0; i-- { if diag == blas.NonUnit { - x[ix] /= cmplx.Conj(ab[i*ldab+k]) + x[ix] /= cmplx.Conj(a[i*lda+k]) } kk := min(k, i) xi := x[ix] jx := ix - kk*incX - for _, aij := range ab[i*ldab+k-kk : i*ldab+k] { + for _, aij := range a[i*lda+k-kk : i*lda+k] { x[jx] -= xi * cmplx.Conj(aij) jx += incX } @@ -1674,24 +2013,41 @@ func (Implementation) Ztbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag // where x is an n element vector and A is an n×n triangular matrix, supplied in // packed form. func (Implementation) Ztpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: } - if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans { + switch trans { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if diag != blas.Unit && diag != blas.NonUnit { + switch diag { + default: panic(badDiag) + case blas.NonUnit, blas.Unit: } - checkZVector('x', n, x, incX) - if len(ap) < n*(n+1)/2 { - panic("blas: insufficient A packed matrix slice length") + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) } + // Quick return if possible. if n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + // Set up start index in X. var kx int if incX < 0 { @@ -1901,24 +2257,41 @@ func (Implementation) Ztpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag // No test for singularity or near-singularity is included in this // routine. Such tests must be performed before calling this routine. func (Implementation) Ztpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex128, x []complex128, incX int) { - if uplo != blas.Upper && uplo != blas.Lower { + switch uplo { + default: panic(badUplo) + case blas.Upper, blas.Lower: } - if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans { + switch trans { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if diag != blas.Unit && diag != blas.NonUnit { + switch diag { + default: panic(badDiag) + case blas.NonUnit, blas.Unit: } - if len(ap) < n*(n+1)/2 { - panic("blas: insufficient A packed matrix slice length") + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) } - checkZVector('x', n, x, incX) + // Quick return if possible. if n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + // Set up start index in X. var kx int if incX < 0 { @@ -1961,7 +2334,7 @@ func (Implementation) Ztpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag if incX == 1 { for i := 0; i < n; i++ { if i > 0 { - x[i] -= c128.DotuUnitary(x[:i], ap[kk:kk+i+1]) + x[i] -= c128.DotuUnitary(x[:i], ap[kk:kk+i]) } if diag == blas.NonUnit { x[i] /= ap[kk+i] @@ -1972,7 +2345,7 @@ func (Implementation) Ztpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag ix := kx for i := 0; i < n; i++ { if i > 0 { - x[ix] -= c128.DotuInc(x, ap[kk:kk+i+1], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + x[ix] -= c128.DotuInc(x, ap[kk:kk+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) } if diag == blas.NonUnit { x[ix] /= ap[kk+i] @@ -2113,22 +2486,44 @@ func (Implementation) Ztpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag // x = A^H * x if trans = blas.ConjTrans // where x is a vector, and A is an n×n triangular matrix. func (Implementation) Ztrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { - if uplo != blas.Upper && uplo != blas.Lower { - panic(badUplo) - } - if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans { + switch trans { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if diag != blas.Unit && diag != blas.NonUnit { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) } - checkZMatrix('A', n, n, a, lda) - checkZVector('x', n, x, incX) + // Quick return if possible. if n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + // Set up start index in X. var kx int if incX < 0 { @@ -2305,22 +2700,44 @@ func (Implementation) Ztrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag // No test for singularity or near-singularity is included in this // routine. Such tests must be performed before calling this routine. func (Implementation) Ztrsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex128, lda int, x []complex128, incX int) { - if uplo != blas.Upper && uplo != blas.Lower { - panic(badUplo) - } - if trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans { + switch trans { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if diag != blas.Unit && diag != blas.NonUnit { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) } - checkZMatrix('A', n, n, a, lda) - checkZVector('x', n, x, incX) + // Quick return if possible. if n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + // Set up start index in X. var kx int if incX < 0 { diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go new file mode 100644 index 00000000000..10faf8f7d8e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2cmplx64.go @@ -0,0 +1,2942 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// 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 gonum + +import ( + cmplx "gonum.org/v1/gonum/internal/cmplx64" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/c64" +) + +var _ blas.Complex64Level2 = Implementation{} + +// Cgbmv performs one of the matrix-vector operations +// y = alpha * A * x + beta * y if trans = blas.NoTrans +// y = alpha * A^T * x + beta * y if trans = blas.Trans +// y = alpha * A^H * x + beta * y if trans = blas.ConjTrans +// where alpha and beta are scalars, x and y are vectors, and A is an m×n band matrix +// with kL sub-diagonals and kU super-diagonals. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cgbmv(trans blas.Transpose, m, n, kL, kU int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if kL < 0 { + panic(kLLT0) + } + if kU < 0 { + panic(kULT0) + } + if lda < kL+kU+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { + panic(shortA) + } + var lenX, lenY int + if trans == blas.NoTrans { + lenX, lenY = n, m + } else { + lenX, lenY = m, n + } + if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + var kx int + if incX < 0 { + kx = (1 - lenX) * incX + } + var ky int + if incY < 0 { + ky = (1 - lenY) * incY + } + + // Form y = beta*y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:lenY] { + y[i] = 0 + } + } else { + c64.ScalUnitary(beta, y[:lenY]) + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < lenY; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + c64.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) + } else { + c64.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) + } + } + } + } + + nRow := min(m, n+kL) + nCol := kL + 1 + kU + switch trans { + case blas.NoTrans: + iy := ky + if incX == 1 { + for i := 0; i < nRow; i++ { + l := max(0, kL-i) + u := min(nCol, n+kL-i) + aRow := a[i*lda+l : i*lda+u] + off := max(0, i-kL) + xtmp := x[off : off+u-l] + var sum complex64 + for j, v := range aRow { + sum += xtmp[j] * v + } + y[iy] += alpha * sum + iy += incY + } + } else { + for i := 0; i < nRow; i++ { + l := max(0, kL-i) + u := min(nCol, n+kL-i) + aRow := a[i*lda+l : i*lda+u] + off := max(0, i-kL) * incX + jx := kx + var sum complex64 + for _, v := range aRow { + sum += x[off+jx] * v + jx += incX + } + y[iy] += alpha * sum + iy += incY + } + } + case blas.Trans: + if incX == 1 { + for i := 0; i < nRow; i++ { + l := max(0, kL-i) + u := min(nCol, n+kL-i) + aRow := a[i*lda+l : i*lda+u] + off := max(0, i-kL) * incY + alphaxi := alpha * x[i] + jy := ky + for _, v := range aRow { + y[off+jy] += alphaxi * v + jy += incY + } + } + } else { + ix := kx + for i := 0; i < nRow; i++ { + l := max(0, kL-i) + u := min(nCol, n+kL-i) + aRow := a[i*lda+l : i*lda+u] + off := max(0, i-kL) * incY + alphaxi := alpha * x[ix] + jy := ky + for _, v := range aRow { + y[off+jy] += alphaxi * v + jy += incY + } + ix += incX + } + } + case blas.ConjTrans: + if incX == 1 { + for i := 0; i < nRow; i++ { + l := max(0, kL-i) + u := min(nCol, n+kL-i) + aRow := a[i*lda+l : i*lda+u] + off := max(0, i-kL) * incY + alphaxi := alpha * x[i] + jy := ky + for _, v := range aRow { + y[off+jy] += alphaxi * cmplx.Conj(v) + jy += incY + } + } + } else { + ix := kx + for i := 0; i < nRow; i++ { + l := max(0, kL-i) + u := min(nCol, n+kL-i) + aRow := a[i*lda+l : i*lda+u] + off := max(0, i-kL) * incY + alphaxi := alpha * x[ix] + jy := ky + for _, v := range aRow { + y[off+jy] += alphaxi * cmplx.Conj(v) + jy += incY + } + ix += incX + } + } + } +} + +// Cgemv performs one of the matrix-vector operations +// y = alpha * A * x + beta * y if trans = blas.NoTrans +// y = alpha * A^T * x + beta * y if trans = blas.Trans +// y = alpha * A^H * x + beta * y if trans = blas.ConjTrans +// where alpha and beta are scalars, x and y are vectors, and A is an m×n dense matrix. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cgemv(trans blas.Transpose, m, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + 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) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + var lenX, lenY int + if trans == blas.NoTrans { + lenX = n + lenY = m + } else { + lenX = m + lenY = n + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + var kx int + if incX < 0 { + kx = (1 - lenX) * incX + } + var ky int + if incY < 0 { + ky = (1 - lenY) * incY + } + + // Form y = beta*y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:lenY] { + y[i] = 0 + } + } else { + c64.ScalUnitary(beta, y[:lenY]) + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < lenY; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + c64.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) + } else { + c64.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) + } + } + } + } + + if alpha == 0 { + return + } + + switch trans { + default: + // Form y = alpha*A*x + y. + iy := ky + if incX == 1 { + for i := 0; i < m; i++ { + y[iy] += alpha * c64.DotuUnitary(a[i*lda:i*lda+n], x[:n]) + iy += incY + } + return + } + for i := 0; i < m; i++ { + y[iy] += alpha * c64.DotuInc(a[i*lda:i*lda+n], x, uintptr(n), 1, uintptr(incX), 0, uintptr(kx)) + iy += incY + } + return + + case blas.Trans: + // Form y = alpha*A^T*x + y. + ix := kx + if incY == 1 { + for i := 0; i < m; i++ { + c64.AxpyUnitary(alpha*x[ix], a[i*lda:i*lda+n], y[:n]) + ix += incX + } + return + } + for i := 0; i < m; i++ { + c64.AxpyInc(alpha*x[ix], a[i*lda:i*lda+n], y, uintptr(n), 1, uintptr(incY), 0, uintptr(ky)) + ix += incX + } + return + + case blas.ConjTrans: + // Form y = alpha*A^H*x + y. + ix := kx + if incY == 1 { + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + for j := 0; j < n; j++ { + y[j] += tmp * cmplx.Conj(a[i*lda+j]) + } + ix += incX + } + return + } + for i := 0; i < m; i++ { + tmp := alpha * x[ix] + jy := ky + for j := 0; j < n; j++ { + y[jy] += tmp * cmplx.Conj(a[i*lda+j]) + jy += incY + } + ix += incX + } + return + } +} + +// Cgerc performs the rank-one operation +// A += alpha * x * y^H +// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, +// and y is an n element vector. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cgerc(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + 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) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { + return + } + + var kx, jy int + if incX < 0 { + kx = (1 - m) * incX + } + if incY < 0 { + jy = (1 - n) * incY + } + for j := 0; j < n; j++ { + if y[jy] != 0 { + tmp := alpha * cmplx.Conj(y[jy]) + c64.AxpyInc(tmp, x, a[j:], uintptr(m), uintptr(incX), uintptr(lda), uintptr(kx), 0) + } + jy += incY + } +} + +// Cgeru performs the rank-one operation +// A += alpha * x * y^T +// where A is an m×n dense matrix, alpha is a scalar, x is an m element vector, +// and y is an n element vector. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cgeru(m, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + 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) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { + return + } + + var kx int + if incX < 0 { + kx = (1 - m) * incX + } + if incY == 1 { + for i := 0; i < m; i++ { + if x[kx] != 0 { + tmp := alpha * x[kx] + c64.AxpyUnitary(tmp, y[:n], a[i*lda:i*lda+n]) + } + kx += incX + } + return + } + var jy int + if incY < 0 { + jy = (1 - n) * incY + } + for i := 0; i < m; i++ { + if x[kx] != 0 { + tmp := alpha * x[kx] + c64.AxpyInc(tmp, y, a[i*lda:i*lda+n], uintptr(n), uintptr(incY), 1, uintptr(jy), 0) + } + kx += incX + } +} + +// Chbmv performs the matrix-vector operation +// y = alpha * A * x + beta * y +// where alpha and beta are scalars, x and y are vectors, and A is an n×n +// Hermitian band matrix with k super-diagonals. The imaginary parts of +// the diagonal elements of A are ignored and assumed to be zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Chbmv(uplo blas.Uplo, n, k int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + // Set up the start indices in X and Y. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + var ky int + if incY < 0 { + ky = (1 - n) * incY + } + + // Form y = beta*y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + for i, v := range y[:n] { + y[i] = beta * v + } + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + for i := 0; i < n; i++ { + y[iy] = beta * y[iy] + iy += incY + } + } + } + } + + if alpha == 0 { + return + } + + // The elements of A are accessed sequentially with one pass through a. + switch uplo { + case blas.Upper: + iy := ky + if incX == 1 { + for i := 0; i < n; i++ { + aRow := a[i*lda:] + alphaxi := alpha * x[i] + sum := alphaxi * complex(real(aRow[0]), 0) + u := min(k+1, n-i) + jy := incY + for j := 1; j < u; j++ { + v := aRow[j] + sum += alpha * x[i+j] * v + y[iy+jy] += alphaxi * cmplx.Conj(v) + jy += incY + } + y[iy] += sum + iy += incY + } + } else { + ix := kx + for i := 0; i < n; i++ { + aRow := a[i*lda:] + alphaxi := alpha * x[ix] + sum := alphaxi * complex(real(aRow[0]), 0) + u := min(k+1, n-i) + jx := incX + jy := incY + for j := 1; j < u; j++ { + v := aRow[j] + sum += alpha * x[ix+jx] * v + y[iy+jy] += alphaxi * cmplx.Conj(v) + jx += incX + jy += incY + } + y[iy] += sum + ix += incX + iy += incY + } + } + case blas.Lower: + iy := ky + if incX == 1 { + for i := 0; i < n; i++ { + l := max(0, k-i) + alphaxi := alpha * x[i] + jy := l * incY + aRow := a[i*lda:] + for j := l; j < k; j++ { + v := aRow[j] + y[iy] += alpha * v * x[i-k+j] + y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) + jy += incY + } + y[iy] += alphaxi * complex(real(aRow[k]), 0) + iy += incY + } + } else { + ix := kx + for i := 0; i < n; i++ { + l := max(0, k-i) + alphaxi := alpha * x[ix] + jx := l * incX + jy := l * incY + aRow := a[i*lda:] + for j := l; j < k; j++ { + v := aRow[j] + y[iy] += alpha * v * x[ix-k*incX+jx] + y[iy-k*incY+jy] += alphaxi * cmplx.Conj(v) + jx += incX + jy += incY + } + y[iy] += alphaxi * complex(real(aRow[k]), 0) + ix += incX + iy += incY + } + } + } +} + +// Chemv performs the matrix-vector operation +// y = alpha * A * x + beta * y +// where alpha and beta are scalars, x and y are vectors, and A is an n×n +// Hermitian matrix. The imaginary parts of the diagonal elements of A are +// ignored and assumed to be zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Chemv(uplo blas.Uplo, n int, alpha complex64, a []complex64, lda int, x []complex64, incX int, beta complex64, y []complex64, incY int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + // Set up the start indices in X and Y. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + var ky int + if incY < 0 { + ky = (1 - n) * incY + } + + // Form y = beta*y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + for i, v := range y[:n] { + y[i] = beta * v + } + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + for i := 0; i < n; i++ { + y[iy] = beta * y[iy] + iy += incY + } + } + } + } + + if alpha == 0 { + return + } + + // The elements of A are accessed sequentially with one pass through + // the triangular part of A. + + if uplo == blas.Upper { + // Form y when A is stored in upper triangle. + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + tmp1 := alpha * x[i] + var tmp2 complex64 + for j := i + 1; j < n; j++ { + y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) + tmp2 += a[i*lda+j] * x[j] + } + aii := complex(real(a[i*lda+i]), 0) + y[i] += tmp1*aii + alpha*tmp2 + } + } else { + ix := kx + iy := ky + for i := 0; i < n; i++ { + tmp1 := alpha * x[ix] + var tmp2 complex64 + jx := ix + jy := iy + for j := i + 1; j < n; j++ { + jx += incX + jy += incY + y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) + tmp2 += a[i*lda+j] * x[jx] + } + aii := complex(real(a[i*lda+i]), 0) + y[iy] += tmp1*aii + alpha*tmp2 + ix += incX + iy += incY + } + } + return + } + + // Form y when A is stored in lower triangle. + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + tmp1 := alpha * x[i] + var tmp2 complex64 + for j := 0; j < i; j++ { + y[j] += tmp1 * cmplx.Conj(a[i*lda+j]) + tmp2 += a[i*lda+j] * x[j] + } + aii := complex(real(a[i*lda+i]), 0) + y[i] += tmp1*aii + alpha*tmp2 + } + } else { + ix := kx + iy := ky + for i := 0; i < n; i++ { + tmp1 := alpha * x[ix] + var tmp2 complex64 + jx := kx + jy := ky + for j := 0; j < i; j++ { + y[jy] += tmp1 * cmplx.Conj(a[i*lda+j]) + tmp2 += a[i*lda+j] * x[jx] + jx += incX + jy += incY + } + aii := complex(real(a[i*lda+i]), 0) + y[iy] += tmp1*aii + alpha*tmp2 + ix += incX + iy += incY + } + } +} + +// Cher performs the Hermitian rank-one operation +// A += alpha * x * x^H +// where A is an n×n Hermitian matrix, alpha is a real scalar, and x is an n +// element vector. On entry, the imaginary parts of the diagonal elements of A +// are ignored and assumed to be zero, on return they will be set to zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cher(uplo blas.Uplo, n int, alpha float32, x []complex64, incX int, a []complex64, lda int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { + return + } + + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + if uplo == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 { + tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii+xtmp, 0) + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[j]) + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + + ix := kx + for i := 0; i < n; i++ { + if x[ix] != 0 { + tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii+xtmp, 0) + jx := ix + incX + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[jx]) + jx += incX + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + } + return + } + + if incX == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 { + tmp := complex(alpha*real(x[i]), alpha*imag(x[i])) + for j := 0; j < i; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[j]) + } + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii+xtmp, 0) + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + + ix := kx + for i := 0; i < n; i++ { + if x[ix] != 0 { + tmp := complex(alpha*real(x[ix]), alpha*imag(x[ix])) + jx := kx + for j := 0; j < i; j++ { + a[i*lda+j] += tmp * cmplx.Conj(x[jx]) + jx += incX + } + aii := real(a[i*lda+i]) + xtmp := real(tmp * cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii+xtmp, 0) + + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + } +} + +// Cher2 performs the Hermitian rank-two operation +// A += alpha * x * y^H + conj(alpha) * y * x^H +// where alpha is a scalar, x and y are n element vectors and A is an n×n +// Hermitian matrix. On entry, the imaginary parts of the diagonal elements are +// ignored and assumed to be zero. On return they will be set to zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cher2(uplo blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, a []complex64, lda int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { + return + } + + var kx, ky int + var ix, iy int + if incX != 1 || incY != 1 { + if incX < 0 { + kx = (1 - n) * incX + } + if incY < 0 { + ky = (1 - n) * incY + } + ix = kx + iy = ky + } + if uplo == blas.Upper { + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[i] + tmp2 := cmplx.Conj(alpha) * y[i] + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii, 0) + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + for i := 0; i < n; i++ { + if x[ix] != 0 || y[iy] != 0 { + tmp1 := alpha * x[ix] + tmp2 := cmplx.Conj(alpha) * y[iy] + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii, 0) + jx := ix + incX + jy := iy + incY + for j := i + 1; j < n; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) + jx += incX + jy += incY + } + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + iy += incY + } + return + } + + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[i] + tmp2 := cmplx.Conj(alpha) * y[i] + for j := 0; j < i; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) + } + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) + a[i*lda+i] = complex(aii, 0) + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + } + return + } + for i := 0; i < n; i++ { + if x[ix] != 0 || y[iy] != 0 { + tmp1 := alpha * x[ix] + tmp2 := cmplx.Conj(alpha) * y[iy] + jx := kx + jy := ky + for j := 0; j < i; j++ { + a[i*lda+j] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) + jx += incX + jy += incY + } + aii := real(a[i*lda+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) + a[i*lda+i] = complex(aii, 0) + } else { + aii := real(a[i*lda+i]) + a[i*lda+i] = complex(aii, 0) + } + ix += incX + iy += incY + } +} + +// Chpmv performs the matrix-vector operation +// y = alpha * A * x + beta * y +// where alpha and beta are scalars, x and y are vectors, and A is an n×n +// Hermitian matrix in packed form. The imaginary parts of the diagonal +// elements of A are ignored and assumed to be zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Chpmv(uplo blas.Uplo, n int, alpha complex64, ap []complex64, x []complex64, incX int, beta complex64, y []complex64, incY int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + // Set up the start indices in X and Y. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + var ky int + if incY < 0 { + ky = (1 - n) * incY + } + + // Form y = beta*y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + for i, v := range y[:n] { + y[i] = beta * v + } + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + for i := 0; i < n; i++ { + y[iy] *= beta + iy += incY + } + } + } + } + + if alpha == 0 { + return + } + + // The elements of A are accessed sequentially with one pass through ap. + + var kk int + if uplo == blas.Upper { + // Form y when ap contains the upper triangle. + // Here, kk points to the current diagonal element in ap. + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + tmp1 := alpha * x[i] + y[i] += tmp1 * complex(real(ap[kk]), 0) + var tmp2 complex64 + k := kk + 1 + for j := i + 1; j < n; j++ { + y[j] += tmp1 * cmplx.Conj(ap[k]) + tmp2 += ap[k] * x[j] + k++ + } + y[i] += alpha * tmp2 + kk += n - i + } + } else { + ix := kx + iy := ky + for i := 0; i < n; i++ { + tmp1 := alpha * x[ix] + y[iy] += tmp1 * complex(real(ap[kk]), 0) + var tmp2 complex64 + jx := ix + jy := iy + for k := kk + 1; k < kk+n-i; k++ { + jx += incX + jy += incY + y[jy] += tmp1 * cmplx.Conj(ap[k]) + tmp2 += ap[k] * x[jx] + } + y[iy] += alpha * tmp2 + ix += incX + iy += incY + kk += n - i + } + } + return + } + + // Form y when ap contains the lower triangle. + // Here, kk points to the beginning of current row in ap. + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + tmp1 := alpha * x[i] + var tmp2 complex64 + k := kk + for j := 0; j < i; j++ { + y[j] += tmp1 * cmplx.Conj(ap[k]) + tmp2 += ap[k] * x[j] + k++ + } + aii := complex(real(ap[kk+i]), 0) + y[i] += tmp1*aii + alpha*tmp2 + kk += i + 1 + } + } else { + ix := kx + iy := ky + for i := 0; i < n; i++ { + tmp1 := alpha * x[ix] + var tmp2 complex64 + jx := kx + jy := ky + for k := kk; k < kk+i; k++ { + y[jy] += tmp1 * cmplx.Conj(ap[k]) + tmp2 += ap[k] * x[jx] + jx += incX + jy += incY + } + aii := complex(real(ap[kk+i]), 0) + y[iy] += tmp1*aii + alpha*tmp2 + ix += incX + iy += incY + kk += i + 1 + } + } +} + +// Chpr performs the Hermitian rank-1 operation +// A += alpha * x * x^H +// where alpha is a real scalar, x is a vector, and A is an n×n hermitian matrix +// in packed form. On entry, the imaginary parts of the diagonal elements are +// assumed to be zero, and on return they are set to zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Chpr(uplo blas.Uplo, n int, alpha float32, x []complex64, incX int, ap []complex64) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. + if alpha == 0 { + return + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + // The elements of A are accessed sequentially with one pass through ap. + + var kk int + if uplo == blas.Upper { + // Form A when upper triangle is stored in AP. + // Here, kk points to the current diagonal element in ap. + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if xi != 0 { + aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) + ap[kk] = complex(aii, 0) + + tmp := complex(alpha, 0) * xi + a := ap[kk+1 : kk+n-i] + x := x[i+1 : n] + for j, v := range x { + a[j] += tmp * cmplx.Conj(v) + } + } else { + ap[kk] = complex(real(ap[kk]), 0) + } + kk += n - i + } + } else { + ix := kx + for i := 0; i < n; i++ { + xi := x[ix] + if xi != 0 { + aii := real(ap[kk]) + alpha*real(cmplx.Conj(xi)*xi) + ap[kk] = complex(aii, 0) + + tmp := complex(alpha, 0) * xi + jx := ix + incX + a := ap[kk+1 : kk+n-i] + for k := range a { + a[k] += tmp * cmplx.Conj(x[jx]) + jx += incX + } + } else { + ap[kk] = complex(real(ap[kk]), 0) + } + ix += incX + kk += n - i + } + } + return + } + + // Form A when lower triangle is stored in AP. + // Here, kk points to the beginning of current row in ap. + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if xi != 0 { + tmp := complex(alpha, 0) * xi + a := ap[kk : kk+i] + for j, v := range x[:i] { + a[j] += tmp * cmplx.Conj(v) + } + + aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) + ap[kk+i] = complex(aii, 0) + } else { + ap[kk+i] = complex(real(ap[kk+i]), 0) + } + kk += i + 1 + } + } else { + ix := kx + for i := 0; i < n; i++ { + xi := x[ix] + if xi != 0 { + tmp := complex(alpha, 0) * xi + a := ap[kk : kk+i] + jx := kx + for k := range a { + a[k] += tmp * cmplx.Conj(x[jx]) + jx += incX + } + + aii := real(ap[kk+i]) + alpha*real(cmplx.Conj(xi)*xi) + ap[kk+i] = complex(aii, 0) + } else { + ap[kk+i] = complex(real(ap[kk+i]), 0) + } + ix += incX + kk += i + 1 + } + } +} + +// Chpr2 performs the Hermitian rank-2 operation +// A += alpha * x * y^H + conj(alpha) * y * x^H +// where alpha is a complex scalar, x and y are n element vectors, and A is an +// n×n Hermitian matrix, supplied in packed form. On entry, the imaginary parts +// of the diagonal elements are assumed to be zero, and on return they are set to zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Chpr2(uplo blas.Uplo, n int, alpha complex64, x []complex64, incX int, y []complex64, incY int, ap []complex64) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + if incY == 0 { + panic(zeroIncY) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. + if alpha == 0 { + return + } + + // Set up start indices in X and Y. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + var ky int + if incY < 0 { + ky = (1 - n) * incY + } + + // The elements of A are accessed sequentially with one pass through ap. + + var kk int + if uplo == blas.Upper { + // Form A when upper triangle is stored in AP. + // Here, kk points to the current diagonal element in ap. + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[i] + tmp2 := cmplx.Conj(alpha) * y[i] + aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) + ap[kk] = complex(aii, 0) + k := kk + 1 + for j := i + 1; j < n; j++ { + ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) + k++ + } + } else { + ap[kk] = complex(real(ap[kk]), 0) + } + kk += n - i + } + } else { + ix := kx + iy := ky + for i := 0; i < n; i++ { + if x[ix] != 0 || y[iy] != 0 { + tmp1 := alpha * x[ix] + tmp2 := cmplx.Conj(alpha) * y[iy] + aii := real(ap[kk]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) + ap[kk] = complex(aii, 0) + jx := ix + incX + jy := iy + incY + for k := kk + 1; k < kk+n-i; k++ { + ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) + jx += incX + jy += incY + } + } else { + ap[kk] = complex(real(ap[kk]), 0) + } + ix += incX + iy += incY + kk += n - i + } + } + return + } + + // Form A when lower triangle is stored in AP. + // Here, kk points to the beginning of current row in ap. + if incX == 1 && incY == 1 { + for i := 0; i < n; i++ { + if x[i] != 0 || y[i] != 0 { + tmp1 := alpha * x[i] + tmp2 := cmplx.Conj(alpha) * y[i] + k := kk + for j := 0; j < i; j++ { + ap[k] += tmp1*cmplx.Conj(y[j]) + tmp2*cmplx.Conj(x[j]) + k++ + } + aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[i])) + real(tmp2*cmplx.Conj(x[i])) + ap[kk+i] = complex(aii, 0) + } else { + ap[kk+i] = complex(real(ap[kk+i]), 0) + } + kk += i + 1 + } + } else { + ix := kx + iy := ky + for i := 0; i < n; i++ { + if x[ix] != 0 || y[iy] != 0 { + tmp1 := alpha * x[ix] + tmp2 := cmplx.Conj(alpha) * y[iy] + jx := kx + jy := ky + for k := kk; k < kk+i; k++ { + ap[k] += tmp1*cmplx.Conj(y[jy]) + tmp2*cmplx.Conj(x[jx]) + jx += incX + jy += incY + } + aii := real(ap[kk+i]) + real(tmp1*cmplx.Conj(y[iy])) + real(tmp2*cmplx.Conj(x[ix])) + ap[kk+i] = complex(aii, 0) + } else { + ap[kk+i] = complex(real(ap[kk+i]), 0) + } + ix += incX + iy += incY + kk += i + 1 + } + } +} + +// Ctbmv performs one of the matrix-vector operations +// x = A * x if trans = blas.NoTrans +// x = A^T * x if trans = blas.Trans +// x = A^H * x if trans = blas.ConjTrans +// where x is an n element vector and A is an n×n triangular band matrix, with +// (k+1) diagonals. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctbmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: + panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + switch trans { + case blas.NoTrans: + if uplo == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + xi := x[i] + if diag == blas.NonUnit { + xi *= a[i*lda] + } + kk := min(k, n-i-1) + for j, aij := range a[i*lda+1 : i*lda+kk+1] { + xi += x[i+j+1] * aij + } + x[i] = xi + } + } else { + ix := kx + for i := 0; i < n; i++ { + xi := x[ix] + if diag == blas.NonUnit { + xi *= a[i*lda] + } + kk := min(k, n-i-1) + jx := ix + incX + for _, aij := range a[i*lda+1 : i*lda+kk+1] { + xi += x[jx] * aij + jx += incX + } + x[ix] = xi + ix += incX + } + } + } else { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + xi := x[i] + if diag == blas.NonUnit { + xi *= a[i*lda+k] + } + kk := min(k, i) + for j, aij := range a[i*lda+k-kk : i*lda+k] { + xi += x[i-kk+j] * aij + } + x[i] = xi + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + xi := x[ix] + if diag == blas.NonUnit { + xi *= a[i*lda+k] + } + kk := min(k, i) + jx := ix - kk*incX + for _, aij := range a[i*lda+k-kk : i*lda+k] { + xi += x[jx] * aij + jx += incX + } + x[ix] = xi + ix -= incX + } + } + } + case blas.Trans: + if uplo == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + kk := min(k, n-i-1) + xi := x[i] + for j, aij := range a[i*lda+1 : i*lda+kk+1] { + x[i+j+1] += xi * aij + } + if diag == blas.NonUnit { + x[i] *= a[i*lda] + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + kk := min(k, n-i-1) + jx := ix + incX + xi := x[ix] + for _, aij := range a[i*lda+1 : i*lda+kk+1] { + x[jx] += xi * aij + jx += incX + } + if diag == blas.NonUnit { + x[ix] *= a[i*lda] + } + ix -= incX + } + } + } else { + if incX == 1 { + for i := 0; i < n; i++ { + kk := min(k, i) + xi := x[i] + for j, aij := range a[i*lda+k-kk : i*lda+k] { + x[i-kk+j] += xi * aij + } + if diag == blas.NonUnit { + x[i] *= a[i*lda+k] + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + kk := min(k, i) + jx := ix - kk*incX + xi := x[ix] + for _, aij := range a[i*lda+k-kk : i*lda+k] { + x[jx] += xi * aij + jx += incX + } + if diag == blas.NonUnit { + x[ix] *= a[i*lda+k] + } + ix += incX + } + } + } + case blas.ConjTrans: + if uplo == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + kk := min(k, n-i-1) + xi := x[i] + for j, aij := range a[i*lda+1 : i*lda+kk+1] { + x[i+j+1] += xi * cmplx.Conj(aij) + } + if diag == blas.NonUnit { + x[i] *= cmplx.Conj(a[i*lda]) + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + kk := min(k, n-i-1) + jx := ix + incX + xi := x[ix] + for _, aij := range a[i*lda+1 : i*lda+kk+1] { + x[jx] += xi * cmplx.Conj(aij) + jx += incX + } + if diag == blas.NonUnit { + x[ix] *= cmplx.Conj(a[i*lda]) + } + ix -= incX + } + } + } else { + if incX == 1 { + for i := 0; i < n; i++ { + kk := min(k, i) + xi := x[i] + for j, aij := range a[i*lda+k-kk : i*lda+k] { + x[i-kk+j] += xi * cmplx.Conj(aij) + } + if diag == blas.NonUnit { + x[i] *= cmplx.Conj(a[i*lda+k]) + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + kk := min(k, i) + jx := ix - kk*incX + xi := x[ix] + for _, aij := range a[i*lda+k-kk : i*lda+k] { + x[jx] += xi * cmplx.Conj(aij) + jx += incX + } + if diag == blas.NonUnit { + x[ix] *= cmplx.Conj(a[i*lda+k]) + } + ix += incX + } + } + } + } +} + +// Ctbsv solves one of the systems of equations +// A * x = b if trans == blas.NoTrans +// A^T * x = b if trans == blas.Trans +// A^H * x = b if trans == blas.ConjTrans +// where b and x are n element vectors and A is an n×n triangular band matrix +// with (k+1) diagonals. +// +// On entry, x contains the values of b, and the solution 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. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctbsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, k int, a []complex64, lda int, x []complex64, incX int) { + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: + panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + switch trans { + case blas.NoTrans: + if uplo == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + kk := min(k, n-i-1) + var sum complex64 + for j, aij := range a[i*lda+1 : i*lda+kk+1] { + sum += x[i+1+j] * aij + } + x[i] -= sum + if diag == blas.NonUnit { + x[i] /= a[i*lda] + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + kk := min(k, n-i-1) + var sum complex64 + jx := ix + incX + for _, aij := range a[i*lda+1 : i*lda+kk+1] { + sum += x[jx] * aij + jx += incX + } + x[ix] -= sum + if diag == blas.NonUnit { + x[ix] /= a[i*lda] + } + ix -= incX + } + } + } else { + if incX == 1 { + for i := 0; i < n; i++ { + kk := min(k, i) + var sum complex64 + for j, aij := range a[i*lda+k-kk : i*lda+k] { + sum += x[i-kk+j] * aij + } + x[i] -= sum + if diag == blas.NonUnit { + x[i] /= a[i*lda+k] + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + kk := min(k, i) + var sum complex64 + jx := ix - kk*incX + for _, aij := range a[i*lda+k-kk : i*lda+k] { + sum += x[jx] * aij + jx += incX + } + x[ix] -= sum + if diag == blas.NonUnit { + x[ix] /= a[i*lda+k] + } + ix += incX + } + } + } + case blas.Trans: + if uplo == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[i] /= a[i*lda] + } + kk := min(k, n-i-1) + xi := x[i] + for j, aij := range a[i*lda+1 : i*lda+kk+1] { + x[i+1+j] -= xi * aij + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[ix] /= a[i*lda] + } + kk := min(k, n-i-1) + xi := x[ix] + jx := ix + incX + for _, aij := range a[i*lda+1 : i*lda+kk+1] { + x[jx] -= xi * aij + jx += incX + } + ix += incX + } + } + } else { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[i] /= a[i*lda+k] + } + kk := min(k, i) + xi := x[i] + for j, aij := range a[i*lda+k-kk : i*lda+k] { + x[i-kk+j] -= xi * aij + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[ix] /= a[i*lda+k] + } + kk := min(k, i) + xi := x[ix] + jx := ix - kk*incX + for _, aij := range a[i*lda+k-kk : i*lda+k] { + x[jx] -= xi * aij + jx += incX + } + ix -= incX + } + } + } + case blas.ConjTrans: + if uplo == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[i] /= cmplx.Conj(a[i*lda]) + } + kk := min(k, n-i-1) + xi := x[i] + for j, aij := range a[i*lda+1 : i*lda+kk+1] { + x[i+1+j] -= xi * cmplx.Conj(aij) + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[ix] /= cmplx.Conj(a[i*lda]) + } + kk := min(k, n-i-1) + xi := x[ix] + jx := ix + incX + for _, aij := range a[i*lda+1 : i*lda+kk+1] { + x[jx] -= xi * cmplx.Conj(aij) + jx += incX + } + ix += incX + } + } + } else { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[i] /= cmplx.Conj(a[i*lda+k]) + } + kk := min(k, i) + xi := x[i] + for j, aij := range a[i*lda+k-kk : i*lda+k] { + x[i-kk+j] -= xi * cmplx.Conj(aij) + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[ix] /= cmplx.Conj(a[i*lda+k]) + } + kk := min(k, i) + xi := x[ix] + jx := ix - kk*incX + for _, aij := range a[i*lda+k-kk : i*lda+k] { + x[jx] -= xi * cmplx.Conj(aij) + jx += incX + } + ix -= incX + } + } + } + } +} + +// Ctpmv performs one of the matrix-vector operations +// x = A * x if trans = blas.NoTrans +// x = A^T * x if trans = blas.Trans +// x = A^H * x if trans = blas.ConjTrans +// where x is an n element vector and A is an n×n triangular matrix, supplied in +// packed form. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctpmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex64, x []complex64, incX int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch diag { + default: + panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + // The elements of A are accessed sequentially with one pass through A. + + if trans == blas.NoTrans { + // Form x = A*x. + if uplo == blas.Upper { + // kk points to the current diagonal element in ap. + kk := 0 + if incX == 1 { + x = x[:n] + for i := range x { + if diag == blas.NonUnit { + x[i] *= ap[kk] + } + if n-i-1 > 0 { + x[i] += c64.DotuUnitary(ap[kk+1:kk+n-i], x[i+1:]) + } + kk += n - i + } + } else { + ix := kx + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[ix] *= ap[kk] + } + if n-i-1 > 0 { + x[ix] += c64.DotuInc(ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) + } + ix += incX + kk += n - i + } + } + } else { + // kk points to the beginning of current row in ap. + kk := n*(n+1)/2 - n + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[i] *= ap[kk+i] + } + if i > 0 { + x[i] += c64.DotuUnitary(ap[kk:kk+i], x[:i]) + } + kk -= i + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[ix] *= ap[kk+i] + } + if i > 0 { + x[ix] += c64.DotuInc(ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + } + ix -= incX + kk -= i + } + } + } + return + } + + if trans == blas.Trans { + // Form x = A^T*x. + if uplo == blas.Upper { + // kk points to the current diagonal element in ap. + kk := n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + xi := x[i] + if diag == blas.NonUnit { + x[i] *= ap[kk] + } + if n-i-1 > 0 { + c64.AxpyUnitary(xi, ap[kk+1:kk+n-i], x[i+1:n]) + } + kk -= n - i + 1 + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + xi := x[ix] + if diag == blas.NonUnit { + x[ix] *= ap[kk] + } + if n-i-1 > 0 { + c64.AxpyInc(xi, ap[kk+1:kk+n-i], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) + } + ix -= incX + kk -= n - i + 1 + } + } + } else { + // kk points to the beginning of current row in ap. + kk := 0 + if incX == 1 { + x = x[:n] + for i := range x { + if i > 0 { + c64.AxpyUnitary(x[i], ap[kk:kk+i], x[:i]) + } + if diag == blas.NonUnit { + x[i] *= ap[kk+i] + } + kk += i + 1 + } + } else { + ix := kx + for i := 0; i < n; i++ { + if i > 0 { + c64.AxpyInc(x[ix], ap[kk:kk+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + } + if diag == blas.NonUnit { + x[ix] *= ap[kk+i] + } + ix += incX + kk += i + 1 + } + } + } + return + } + + // Form x = A^H*x. + if uplo == blas.Upper { + // kk points to the current diagonal element in ap. + kk := n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + xi := x[i] + if diag == blas.NonUnit { + x[i] *= cmplx.Conj(ap[kk]) + } + k := kk + 1 + for j := i + 1; j < n; j++ { + x[j] += xi * cmplx.Conj(ap[k]) + k++ + } + kk -= n - i + 1 + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + xi := x[ix] + if diag == blas.NonUnit { + x[ix] *= cmplx.Conj(ap[kk]) + } + jx := ix + incX + k := kk + 1 + for j := i + 1; j < n; j++ { + x[jx] += xi * cmplx.Conj(ap[k]) + jx += incX + k++ + } + ix -= incX + kk -= n - i + 1 + } + } + } else { + // kk points to the beginning of current row in ap. + kk := 0 + if incX == 1 { + x = x[:n] + for i, xi := range x { + for j := 0; j < i; j++ { + x[j] += xi * cmplx.Conj(ap[kk+j]) + } + if diag == blas.NonUnit { + x[i] *= cmplx.Conj(ap[kk+i]) + } + kk += i + 1 + } + } else { + ix := kx + for i := 0; i < n; i++ { + xi := x[ix] + jx := kx + for j := 0; j < i; j++ { + x[jx] += xi * cmplx.Conj(ap[kk+j]) + jx += incX + } + if diag == blas.NonUnit { + x[ix] *= cmplx.Conj(ap[kk+i]) + } + ix += incX + kk += i + 1 + } + } + } +} + +// Ctpsv solves one of the systems of equations +// A * x = b if trans == blas.NoTrans +// A^T * x = b if trans == blas.Trans +// A^H * x = b if trans == blas.ConjTrans +// where b and x are n element vectors and A is an n×n triangular matrix in +// packed form. +// +// On entry, x contains the values of b, and the solution 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. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctpsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, ap []complex64, x []complex64, incX int) { + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch diag { + default: + panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + // The elements of A are accessed sequentially with one pass through ap. + + if trans == blas.NoTrans { + // Form x = inv(A)*x. + if uplo == blas.Upper { + kk := n*(n+1)/2 - 1 + if incX == 1 { + for i := n - 1; i >= 0; i-- { + aii := ap[kk] + if n-i-1 > 0 { + x[i] -= c64.DotuUnitary(x[i+1:n], ap[kk+1:kk+n-i]) + } + if diag == blas.NonUnit { + x[i] /= aii + } + kk -= n - i + 1 + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + aii := ap[kk] + if n-i-1 > 0 { + x[ix] -= c64.DotuInc(x, ap[kk+1:kk+n-i], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) + } + if diag == blas.NonUnit { + x[ix] /= aii + } + ix -= incX + kk -= n - i + 1 + } + } + } else { + kk := 0 + if incX == 1 { + for i := 0; i < n; i++ { + if i > 0 { + x[i] -= c64.DotuUnitary(x[:i], ap[kk:kk+i]) + } + if diag == blas.NonUnit { + x[i] /= ap[kk+i] + } + kk += i + 1 + } + } else { + ix := kx + for i := 0; i < n; i++ { + if i > 0 { + x[ix] -= c64.DotuInc(x, ap[kk:kk+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + } + if diag == blas.NonUnit { + x[ix] /= ap[kk+i] + } + ix += incX + kk += i + 1 + } + } + } + return + } + + if trans == blas.Trans { + // Form x = inv(A^T)*x. + if uplo == blas.Upper { + kk := 0 + if incX == 1 { + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[j] /= ap[kk] + } + if n-j-1 > 0 { + c64.AxpyUnitary(-x[j], ap[kk+1:kk+n-j], x[j+1:n]) + } + kk += n - j + } + } else { + jx := kx + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[jx] /= ap[kk] + } + if n-j-1 > 0 { + c64.AxpyInc(-x[jx], ap[kk+1:kk+n-j], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) + } + jx += incX + kk += n - j + } + } + } else { + kk := n*(n+1)/2 - n + if incX == 1 { + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[j] /= ap[kk+j] + } + if j > 0 { + c64.AxpyUnitary(-x[j], ap[kk:kk+j], x[:j]) + } + kk -= j + } + } else { + jx := kx + (n-1)*incX + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[jx] /= ap[kk+j] + } + if j > 0 { + c64.AxpyInc(-x[jx], ap[kk:kk+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) + } + jx -= incX + kk -= j + } + } + } + return + } + + // Form x = inv(A^H)*x. + if uplo == blas.Upper { + kk := 0 + if incX == 1 { + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[j] /= cmplx.Conj(ap[kk]) + } + xj := x[j] + k := kk + 1 + for i := j + 1; i < n; i++ { + x[i] -= xj * cmplx.Conj(ap[k]) + k++ + } + kk += n - j + } + } else { + jx := kx + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[jx] /= cmplx.Conj(ap[kk]) + } + xj := x[jx] + ix := jx + incX + k := kk + 1 + for i := j + 1; i < n; i++ { + x[ix] -= xj * cmplx.Conj(ap[k]) + ix += incX + k++ + } + jx += incX + kk += n - j + } + } + } else { + kk := n*(n+1)/2 - n + if incX == 1 { + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[j] /= cmplx.Conj(ap[kk+j]) + } + xj := x[j] + for i := 0; i < j; i++ { + x[i] -= xj * cmplx.Conj(ap[kk+i]) + } + kk -= j + } + } else { + jx := kx + (n-1)*incX + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[jx] /= cmplx.Conj(ap[kk+j]) + } + xj := x[jx] + ix := kx + for i := 0; i < j; i++ { + x[ix] -= xj * cmplx.Conj(ap[kk+i]) + ix += incX + } + jx -= incX + kk -= j + } + } + } +} + +// Ctrmv performs one of the matrix-vector operations +// x = A * x if trans = blas.NoTrans +// x = A^T * x if trans = blas.Trans +// x = A^H * x if trans = blas.ConjTrans +// where x is a vector, and A is an n×n triangular matrix. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctrmv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: + panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + // The elements of A are accessed sequentially with one pass through A. + + if trans == blas.NoTrans { + // Form x = A*x. + if uplo == blas.Upper { + if incX == 1 { + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[i] *= a[i*lda+i] + } + if n-i-1 > 0 { + x[i] += c64.DotuUnitary(a[i*lda+i+1:i*lda+n], x[i+1:n]) + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + if diag == blas.NonUnit { + x[ix] *= a[i*lda+i] + } + if n-i-1 > 0 { + x[ix] += c64.DotuInc(a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) + } + ix += incX + } + } + } else { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[i] *= a[i*lda+i] + } + if i > 0 { + x[i] += c64.DotuUnitary(a[i*lda:i*lda+i], x[:i]) + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + if diag == blas.NonUnit { + x[ix] *= a[i*lda+i] + } + if i > 0 { + x[ix] += c64.DotuInc(a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + } + ix -= incX + } + } + } + return + } + + if trans == blas.Trans { + // Form x = A^T*x. + if uplo == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + xi := x[i] + if diag == blas.NonUnit { + x[i] *= a[i*lda+i] + } + if n-i-1 > 0 { + c64.AxpyUnitary(xi, a[i*lda+i+1:i*lda+n], x[i+1:n]) + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + xi := x[ix] + if diag == blas.NonUnit { + x[ix] *= a[i*lda+i] + } + if n-i-1 > 0 { + c64.AxpyInc(xi, a[i*lda+i+1:i*lda+n], x, uintptr(n-i-1), 1, uintptr(incX), 0, uintptr(ix+incX)) + } + ix -= incX + } + } + } else { + if incX == 1 { + for i := 0; i < n; i++ { + if i > 0 { + c64.AxpyUnitary(x[i], a[i*lda:i*lda+i], x[:i]) + } + if diag == blas.NonUnit { + x[i] *= a[i*lda+i] + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + if i > 0 { + c64.AxpyInc(x[ix], a[i*lda:i*lda+i], x, uintptr(i), 1, uintptr(incX), 0, uintptr(kx)) + } + if diag == blas.NonUnit { + x[ix] *= a[i*lda+i] + } + ix += incX + } + } + } + return + } + + // Form x = A^H*x. + if uplo == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + xi := x[i] + if diag == blas.NonUnit { + x[i] *= cmplx.Conj(a[i*lda+i]) + } + for j := i + 1; j < n; j++ { + x[j] += xi * cmplx.Conj(a[i*lda+j]) + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + xi := x[ix] + if diag == blas.NonUnit { + x[ix] *= cmplx.Conj(a[i*lda+i]) + } + jx := ix + incX + for j := i + 1; j < n; j++ { + x[jx] += xi * cmplx.Conj(a[i*lda+j]) + jx += incX + } + ix -= incX + } + } + } else { + if incX == 1 { + for i := 0; i < n; i++ { + for j := 0; j < i; j++ { + x[j] += x[i] * cmplx.Conj(a[i*lda+j]) + } + if diag == blas.NonUnit { + x[i] *= cmplx.Conj(a[i*lda+i]) + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + jx := kx + for j := 0; j < i; j++ { + x[jx] += x[ix] * cmplx.Conj(a[i*lda+j]) + jx += incX + } + if diag == blas.NonUnit { + x[ix] *= cmplx.Conj(a[i*lda+i]) + } + ix += incX + } + } + } +} + +// Ctrsv solves one of the systems of equations +// A * x = b if trans == blas.NoTrans +// A^T * x = b if trans == blas.Trans +// A^H * x = b if trans == blas.ConjTrans +// where b and x are n element vectors and A is an n×n triangular matrix. +// +// On entry, x contains the values of b, and the solution 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. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctrsv(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n int, a []complex64, lda int, x []complex64, incX int) { + switch trans { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch uplo { + default: + panic(badUplo) + case blas.Upper, blas.Lower: + } + switch diag { + default: + panic(badDiag) + case blas.NonUnit, blas.Unit: + } + if n < 0 { + panic(nLT0) + } + if lda < max(1, n) { + panic(badLdA) + } + if incX == 0 { + panic(zeroIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + + // Set up start index in X. + var kx int + if incX < 0 { + kx = (1 - n) * incX + } + + // The elements of A are accessed sequentially with one pass through A. + + if trans == blas.NoTrans { + // Form x = inv(A)*x. + if uplo == blas.Upper { + if incX == 1 { + for i := n - 1; i >= 0; i-- { + aii := a[i*lda+i] + if n-i-1 > 0 { + x[i] -= c64.DotuUnitary(x[i+1:n], a[i*lda+i+1:i*lda+n]) + } + if diag == blas.NonUnit { + x[i] /= aii + } + } + } else { + ix := kx + (n-1)*incX + for i := n - 1; i >= 0; i-- { + aii := a[i*lda+i] + if n-i-1 > 0 { + x[ix] -= c64.DotuInc(x, a[i*lda+i+1:i*lda+n], uintptr(n-i-1), uintptr(incX), 1, uintptr(ix+incX), 0) + } + if diag == blas.NonUnit { + x[ix] /= aii + } + ix -= incX + } + } + } else { + if incX == 1 { + for i := 0; i < n; i++ { + if i > 0 { + x[i] -= c64.DotuUnitary(x[:i], a[i*lda:i*lda+i]) + } + if diag == blas.NonUnit { + x[i] /= a[i*lda+i] + } + } + } else { + ix := kx + for i := 0; i < n; i++ { + if i > 0 { + x[ix] -= c64.DotuInc(x, a[i*lda:i*lda+i], uintptr(i), uintptr(incX), 1, uintptr(kx), 0) + } + if diag == blas.NonUnit { + x[ix] /= a[i*lda+i] + } + ix += incX + } + } + } + return + } + + if trans == blas.Trans { + // Form x = inv(A^T)*x. + if uplo == blas.Upper { + if incX == 1 { + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[j] /= a[j*lda+j] + } + if n-j-1 > 0 { + c64.AxpyUnitary(-x[j], a[j*lda+j+1:j*lda+n], x[j+1:n]) + } + } + } else { + jx := kx + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[jx] /= a[j*lda+j] + } + if n-j-1 > 0 { + c64.AxpyInc(-x[jx], a[j*lda+j+1:j*lda+n], x, uintptr(n-j-1), 1, uintptr(incX), 0, uintptr(jx+incX)) + } + jx += incX + } + } + } else { + if incX == 1 { + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[j] /= a[j*lda+j] + } + xj := x[j] + if j > 0 { + c64.AxpyUnitary(-xj, a[j*lda:j*lda+j], x[:j]) + } + } + } else { + jx := kx + (n-1)*incX + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[jx] /= a[j*lda+j] + } + if j > 0 { + c64.AxpyInc(-x[jx], a[j*lda:j*lda+j], x, uintptr(j), 1, uintptr(incX), 0, uintptr(kx)) + } + jx -= incX + } + } + } + return + } + + // Form x = inv(A^H)*x. + if uplo == blas.Upper { + if incX == 1 { + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[j] /= cmplx.Conj(a[j*lda+j]) + } + xj := x[j] + for i := j + 1; i < n; i++ { + x[i] -= xj * cmplx.Conj(a[j*lda+i]) + } + } + } else { + jx := kx + for j := 0; j < n; j++ { + if diag == blas.NonUnit { + x[jx] /= cmplx.Conj(a[j*lda+j]) + } + xj := x[jx] + ix := jx + incX + for i := j + 1; i < n; i++ { + x[ix] -= xj * cmplx.Conj(a[j*lda+i]) + ix += incX + } + jx += incX + } + } + } else { + if incX == 1 { + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[j] /= cmplx.Conj(a[j*lda+j]) + } + xj := x[j] + for i := 0; i < j; i++ { + x[i] -= xj * cmplx.Conj(a[j*lda+i]) + } + } + } else { + jx := kx + (n-1)*incX + for j := n - 1; j >= 0; j-- { + if diag == blas.NonUnit { + x[jx] /= cmplx.Conj(a[j*lda+j]) + } + xj := x[jx] + ix := kx + for i := 0; i < j; i++ { + x[ix] -= xj * cmplx.Conj(a[j*lda+i]) + ix += incX + } + jx -= incX + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2single.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go similarity index 82% rename from vendor/gonum.org/v1/gonum/blas/gonum/level2single.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go index 7bc8b0d4319..08e1927f79c 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2single.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2float32.go @@ -19,34 +19,40 @@ var _ blas.Float32Level2 = Implementation{} // // 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") + panic(mLT0) } if n < 0 { panic(nLT0) } + if lda < max(1, n) { + panic(badLdA) + } 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 { + return } - // Quick return if possible - if m == 0 || n == 0 || alpha == 0 { + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } f32.Ger(uintptr(m), uintptr(n), @@ -76,7 +82,7 @@ func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, if kL < 0 { panic(kLLT0) } - if kL < 0 { + if kU < 0 { panic(kULT0) } if lda < kL+kU+1 { @@ -88,25 +94,31 @@ func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, if incY == 0 { panic(zeroIncY) } - // Set up indexes + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { + panic(shortA) + } 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 (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { + panic(shortX) } - if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { - panic(badY) - } - if lda*(min(m, n+kL)-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { - panic(badLdA) + if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { + panic(shortY) } - // Quick return if possible - if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -118,11 +130,31 @@ func (Implementation) Sgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float32, 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) + // Form y = beta * y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:lenY] { + y[i] = 0 + } + } else { + f32.ScalUnitary(beta, y[:lenY]) + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < lenY; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f32.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) + } else { + f32.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) + } + } + } } if alpha == 0 { @@ -216,21 +248,26 @@ func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, if n < 0 { panic(nLT0) } - if lda < n { + if 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) - } - if lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + nonUnit := d != blas.Unit if n == 1 { if nonUnit { @@ -253,8 +290,7 @@ func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, } else { tmp = x[i] } - xtmp := x[i+1:] - x[i] = tmp + f32.DotUnitary(a[ilda+i+1:ilda+n], xtmp) + x[i] = tmp + f32.DotUnitary(a[ilda+i+1:ilda+n], x[i+1:n]) } return } @@ -281,7 +317,7 @@ func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, } else { tmp = x[i] } - x[i] = tmp + f32.DotUnitary(a[ilda:ilda+i], x) + x[i] = tmp + f32.DotUnitary(a[ilda:ilda+i], x[:i]) } return } @@ -328,7 +364,7 @@ func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, for i := 0; i < n; i++ { ilda := i * lda xi := x[i] - f32.AxpyUnitary(xi, a[ilda:ilda+i], x) + f32.AxpyUnitary(xi, a[ilda:ilda+i], x[:i]) if nonUnit { x[i] *= a[i*lda+i] } @@ -360,8 +396,6 @@ func (Implementation) Strmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, // // 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) } @@ -374,19 +408,26 @@ func (Implementation) Strsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, if n < 0 { panic(nLT0) } - if lda*(n-1)+n > len(a) || lda < max(1, n) { + if 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 + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if n == 1 { if d == blas.NonUnit { x[0] /= a[0] @@ -532,14 +573,13 @@ func (Implementation) Strsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, // // 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(nLT0) } - if lda > 1 && lda < n { + if lda < max(1, n) { panic(badLdA) } if incX == 0 { @@ -548,17 +588,25 @@ func (Implementation) Ssymv(ul blas.Uplo, n int, alpha float32, a []float32, lda if incY == 0 { panic(zeroIncY) } - 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 (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) } - if lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - // Quick return if possible - if n == 0 || (alpha == 0 && beta == 1) { + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -573,10 +621,28 @@ func (Implementation) Ssymv(ul blas.Uplo, n int, alpha float32, a []float32, lda // Form y = beta * y if beta != 1 { - if incY > 0 { - Implementation{}.Sscal(n, beta, y, incY) + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + f32.ScalUnitary(beta, y[:n]) + } } else { - Implementation{}.Sscal(n, beta, y, -incY) + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f32.ScalInc(beta, y, uintptr(n), uintptr(incY)) + } else { + f32.ScalInc(beta, y, uintptr(n), uintptr(-incY)) + } + } } } @@ -692,18 +758,26 @@ func (Implementation) Stbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k i if k < 0 { panic(kLT0) } - if lda*(n-1)+k+1 > len(a) || lda < k+1 { + if 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -880,7 +954,6 @@ func (Implementation) Stbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k i // // 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) } @@ -893,18 +966,23 @@ func (Implementation) Stpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -1076,18 +1154,29 @@ func (Implementation) Stbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k i if n < 0 { panic(nLT0) } - if lda*(n-1)+k+1 > len(a) || lda < k+1 { + if k < 0 { + panic(kLT0) + } + if 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -1276,25 +1365,37 @@ func (Implementation) Ssbmv(ul blas.Uplo, n, k int, alpha float32, a []float32, if n < 0 { panic(nLT0) } - + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + 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)+k+1 > len(a) || lda < k+1 { - panic(badLdA) + + // Quick return if possible. + if n == 0 { + return } - // Quick return if possible - if n == 0 || (alpha == 0 && beta == 1) { + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -1309,11 +1410,31 @@ func (Implementation) Ssbmv(ul blas.Uplo, n, k int, alpha float32, a []float32, 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) + // Form y = beta * y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + f32.ScalUnitary(beta, y[:n]) + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f32.ScalInc(beta, y, uintptr(n), uintptr(incY)) + } else { + f32.ScalInc(beta, y, uintptr(n), uintptr(-incY)) + } + } + } } if alpha == 0 { @@ -1415,16 +1536,28 @@ func (Implementation) Ssyr(ul blas.Uplo, n int, alpha float32, x []float32, incX if n < 0 { panic(nLT0) } + if 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 lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if alpha == 0 || n == 0 { + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -1503,21 +1636,33 @@ func (Implementation) Ssyr2(ul blas.Uplo, n int, alpha float32, x []float32, inc if n < 0 { panic(nLT0) } + if lda < max(1, 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) + + // Quick return if possible. + if n == 0 { + return } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. if alpha == 0 { return } @@ -1601,7 +1746,6 @@ func (Implementation) Ssyr2(ul blas.Uplo, n int, alpha float32, x []float32, inc // // 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) } @@ -1614,18 +1758,23 @@ func (Implementation) Stpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -1776,31 +1925,38 @@ func (Implementation) Stpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, // 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 +func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, ap []float32, 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 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) + + // Quick return if possible. + if n == 0 { + return } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) } - // Quick return if possible - if n == 0 || (alpha == 0 && beta == 1) { + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -1813,12 +1969,30 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ ky = -(n - 1) * incY } - // Form y = beta * y + // Form y = beta * y. if beta != 1 { - if incY > 0 { - Implementation{}.Sscal(n, beta, y, incY) + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + f32.ScalUnitary(beta, y[:n]) + } } else { - Implementation{}.Sscal(n, beta, y, -incY) + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f32.ScalInc(beta, y, uintptr(n), uintptr(incY)) + } else { + f32.ScalInc(beta, y, uintptr(n), uintptr(-incY)) + } + } } } @@ -1827,7 +2001,7 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ } if n == 1 { - y[0] += alpha * a[0] * x[0] + y[0] += alpha * ap[0] * x[0] return } var offset int // Offset is the index of (i,i). @@ -1836,8 +2010,8 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ iy := ky for i := 0; i < n; i++ { xv := x[i] * alpha - sum := a[offset] * x[i] - atmp := a[offset+1 : offset+n-i] + sum := ap[offset] * x[i] + atmp := ap[offset+1 : offset+n-i] xtmp := x[i+1:] jy := ky + (i+1)*incY for j, v := range atmp { @@ -1855,8 +2029,8 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ iy := ky for i := 0; i < n; i++ { xv := x[ix] * alpha - sum := a[offset] * x[ix] - atmp := a[offset+1 : offset+n-i] + sum := ap[offset] * x[ix] + atmp := ap[offset+1 : offset+n-i] jx := kx + (i+1)*incX jy := ky + (i+1)*incY for _, v := range atmp { @@ -1876,7 +2050,7 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ iy := ky for i := 0; i < n; i++ { xv := x[i] * alpha - atmp := a[offset-i : offset] + atmp := ap[offset-i : offset] jy := ky var sum float32 for j, v := range atmp { @@ -1884,7 +2058,7 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ y[jy] += v * xv jy += incY } - sum += a[offset] * x[i] + sum += ap[offset] * x[i] y[iy] += alpha * sum iy += incY offset += i + 2 @@ -1895,7 +2069,7 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ iy := ky for i := 0; i < n; i++ { xv := x[ix] * alpha - atmp := a[offset-i : offset] + atmp := ap[offset-i : offset] jx := kx jy := ky var sum float32 @@ -1906,7 +2080,7 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ jy += incY } - sum += a[offset] * x[ix] + sum += ap[offset] * x[ix] y[iy] += alpha * sum ix += incX iy += incY @@ -1920,7 +2094,7 @@ func (Implementation) Sspmv(ul blas.Uplo, n int, alpha float32, a []float32, x [ // 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) { +func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX int, ap []float32) { if ul != blas.Lower && ul != blas.Upper { panic(badUplo) } @@ -1930,15 +2104,25 @@ func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX 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 { + + // Quick return if possible. + if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. + if alpha == 0 { + return + } + lenX := n var kx int if incX < 0 { @@ -1948,7 +2132,7 @@ func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX if ul == blas.Upper { if incX == 1 { for i := 0; i < n; i++ { - atmp := a[offset:] + atmp := ap[offset:] xv := alpha * x[i] xtmp := x[i:n] for j, v := range xtmp { @@ -1961,7 +2145,7 @@ func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX ix := kx for i := 0; i < n; i++ { jx := kx + i*incX - atmp := a[offset:] + atmp := ap[offset:] xv := alpha * x[ix] for j := 0; j < n-i; j++ { atmp[j] += xv * x[jx] @@ -1974,7 +2158,7 @@ func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX } if incX == 1 { for i := 0; i < n; i++ { - atmp := a[offset-i:] + atmp := ap[offset-i:] xv := alpha * x[i] xtmp := x[:i+1] for j, v := range xtmp { @@ -1987,7 +2171,7 @@ func (Implementation) Sspr(ul blas.Uplo, n int, alpha float32, x []float32, incX ix := kx for i := 0; i < n; i++ { jx := kx - atmp := a[offset-i:] + atmp := ap[offset-i:] xv := alpha * x[ix] for j := 0; j <= i; j++ { atmp[j] += xv * x[jx] @@ -2017,18 +2201,28 @@ func (Implementation) Sspr2(ul blas.Uplo, n int, alpha float32, x []float32, inc if incY == 0 { panic(zeroIncY) } - 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 (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if len(ap) < (n*(n+1))/2 { - panic(badLdA) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. if alpha == 0 { return } + var ky, kx int if incY < 0 { ky = -(n - 1) * incY diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level2double.go b/vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go similarity index 81% rename from vendor/gonum.org/v1/gonum/blas/gonum/level2double.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go index ce5f9ed16e6..261257888d9 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level2double.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level2float64.go @@ -15,34 +15,40 @@ var _ blas.Float64Level2 = Implementation{} // 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") + panic(mLT0) } if n < 0 { panic(nLT0) } + if lda < max(1, n) { + panic(badLdA) + } 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 { + return } - // Quick return if possible - if m == 0 || n == 0 || alpha == 0 { + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (m-1)*incX) || (incX < 0 && len(x) <= (1-m)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + if len(a) < lda*(m-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } f64.Ger(uintptr(m), uintptr(n), @@ -70,7 +76,7 @@ func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, if kL < 0 { panic(kLLT0) } - if kL < 0 { + if kU < 0 { panic(kULT0) } if lda < kL+kU+1 { @@ -82,25 +88,31 @@ func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, if incY == 0 { panic(zeroIncY) } - // Set up indexes + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(min(m, n+kL)-1)+kL+kU+1 { + panic(shortA) + } 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 (incX > 0 && len(x) <= (lenX-1)*incX) || (incX < 0 && len(x) <= (1-lenX)*incX) { + panic(shortX) } - if (incY > 0 && (lenY-1)*incY >= len(y)) || (incY < 0 && (1-lenY)*incY >= len(y)) { - panic(badY) - } - if lda*(min(m, n+kL)-1)+kL+kU+1 > len(a) || lda < kL+kU+1 { - panic(badLdA) + if (incY > 0 && len(y) <= (lenY-1)*incY) || (incY < 0 && len(y) <= (1-lenY)*incY) { + panic(shortY) } - // Quick return if possible - if m == 0 || n == 0 || (alpha == 0 && beta == 1) { + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -112,11 +124,31 @@ func (Implementation) Dgbmv(tA blas.Transpose, m, n, kL, kU int, alpha float64, 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) + // Form y = beta * y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:lenY] { + y[i] = 0 + } + } else { + f64.ScalUnitary(beta, y[:lenY]) + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < lenY; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f64.ScalInc(beta, y, uintptr(lenY), uintptr(incY)) + } else { + f64.ScalInc(beta, y, uintptr(lenY), uintptr(-incY)) + } + } + } } if alpha == 0 { @@ -208,21 +240,26 @@ func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, if n < 0 { panic(nLT0) } - if lda < n { + if 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) - } - if lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + nonUnit := d != blas.Unit if n == 1 { if nonUnit { @@ -245,8 +282,7 @@ func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, } else { tmp = x[i] } - xtmp := x[i+1:] - x[i] = tmp + f64.DotUnitary(a[ilda+i+1:ilda+n], xtmp) + x[i] = tmp + f64.DotUnitary(a[ilda+i+1:ilda+n], x[i+1:n]) } return } @@ -273,7 +309,7 @@ func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, } else { tmp = x[i] } - x[i] = tmp + f64.DotUnitary(a[ilda:ilda+i], x) + x[i] = tmp + f64.DotUnitary(a[ilda:ilda+i], x[:i]) } return } @@ -320,7 +356,7 @@ func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, for i := 0; i < n; i++ { ilda := i * lda xi := x[i] - f64.AxpyUnitary(xi, a[ilda:ilda+i], x) + f64.AxpyUnitary(xi, a[ilda:ilda+i], x[:i]) if nonUnit { x[i] *= a[i*lda+i] } @@ -350,8 +386,6 @@ func (Implementation) Dtrmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, // 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) } @@ -364,19 +398,26 @@ func (Implementation) Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, if n < 0 { panic(nLT0) } - if lda*(n-1)+n > len(a) || lda < max(1, n) { + if 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 + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if n == 1 { if d == blas.NonUnit { x[0] /= a[0] @@ -520,14 +561,13 @@ func (Implementation) Dtrsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, // 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(nLT0) } - if lda > 1 && lda < n { + if lda < max(1, n) { panic(badLdA) } if incX == 0 { @@ -536,17 +576,25 @@ func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda if incY == 0 { panic(zeroIncY) } - 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 (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+n { + panic(shortA) } - if lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - // Quick return if possible - if n == 0 || (alpha == 0 && beta == 1) { + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -561,10 +609,28 @@ func (Implementation) Dsymv(ul blas.Uplo, n int, alpha float64, a []float64, lda // Form y = beta * y if beta != 1 { - if incY > 0 { - Implementation{}.Dscal(n, beta, y, incY) + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + f64.ScalUnitary(beta, y[:n]) + } } else { - Implementation{}.Dscal(n, beta, y, -incY) + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f64.ScalInc(beta, y, uintptr(n), uintptr(incY)) + } else { + f64.ScalInc(beta, y, uintptr(n), uintptr(-incY)) + } + } } } @@ -678,18 +744,26 @@ func (Implementation) Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k i if k < 0 { panic(kLT0) } - if lda*(n-1)+k+1 > len(a) || lda < k+1 { + if 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -864,7 +938,6 @@ func (Implementation) Dtbmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k i // x = A^T * x if tA == blas.Trans or blas.ConjTrans // where A is an n×n 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) } @@ -877,18 +950,23 @@ func (Implementation) Dtpmv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -1058,18 +1136,29 @@ func (Implementation) Dtbsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n, k i if n < 0 { panic(nLT0) } - if lda*(n-1)+k+1 > len(a) || lda < k+1 { + if k < 0 { + panic(kLT0) + } + if 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -1256,25 +1345,37 @@ func (Implementation) Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, if n < 0 { panic(nLT0) } - + if k < 0 { + panic(kLT0) + } + if lda < k+1 { + 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)+k+1 > len(a) || lda < k+1 { - panic(badLdA) + + // Quick return if possible. + if n == 0 { + return } - // Quick return if possible - if n == 0 || (alpha == 0 && beta == 1) { + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(n-1)+k+1 { + panic(shortA) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -1289,11 +1390,31 @@ func (Implementation) Dsbmv(ul blas.Uplo, n, k int, alpha float64, a []float64, 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) + // Form y = beta * y. + if beta != 1 { + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + f64.ScalUnitary(beta, y[:n]) + } + } else { + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f64.ScalInc(beta, y, uintptr(n), uintptr(incY)) + } else { + f64.ScalInc(beta, y, uintptr(n), uintptr(-incY)) + } + } + } } if alpha == 0 { @@ -1393,16 +1514,28 @@ func (Implementation) Dsyr(ul blas.Uplo, n int, alpha float64, x []float64, incX if n < 0 { panic(nLT0) } + if 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 lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if alpha == 0 || n == 0 { + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. + if alpha == 0 { return } @@ -1479,21 +1612,33 @@ func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, inc if n < 0 { panic(nLT0) } + if lda < max(1, 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) + + // Quick return if possible. + if n == 0 { + return } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if lda*(n-1)+n > len(a) || lda < max(1, n) { - panic(badLdA) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } + if len(a) < lda*(n-1)+n { + panic(shortA) + } + + // Quick return if possible. if alpha == 0 { return } @@ -1575,7 +1720,6 @@ func (Implementation) Dsyr2(ul blas.Uplo, n int, alpha float64, x []float64, inc // 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) } @@ -1588,18 +1732,23 @@ func (Implementation) Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, 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) - } + + // Quick return if possible. if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + var kx int if incX < 0 { kx = -(n - 1) * incX @@ -1748,31 +1897,38 @@ func (Implementation) Dtpsv(ul blas.Uplo, tA blas.Transpose, d blas.Diag, n int, // 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 +func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, ap []float64, 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 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) + + // Quick return if possible. + if n == 0 { + return } - if (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(ap) < n*(n+1)/2 { + panic(shortAP) } - // Quick return if possible - if n == 0 || (alpha == 0 && beta == 1) { + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { return } @@ -1785,12 +1941,30 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ ky = -(n - 1) * incY } - // Form y = beta * y + // Form y = beta * y. if beta != 1 { - if incY > 0 { - Implementation{}.Dscal(n, beta, y, incY) + if incY == 1 { + if beta == 0 { + for i := range y[:n] { + y[i] = 0 + } + } else { + f64.ScalUnitary(beta, y[:n]) + } } else { - Implementation{}.Dscal(n, beta, y, -incY) + iy := ky + if beta == 0 { + for i := 0; i < n; i++ { + y[iy] = 0 + iy += incY + } + } else { + if incY > 0 { + f64.ScalInc(beta, y, uintptr(n), uintptr(incY)) + } else { + f64.ScalInc(beta, y, uintptr(n), uintptr(-incY)) + } + } } } @@ -1799,7 +1973,7 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ } if n == 1 { - y[0] += alpha * a[0] * x[0] + y[0] += alpha * ap[0] * x[0] return } var offset int // Offset is the index of (i,i). @@ -1808,8 +1982,8 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ iy := ky for i := 0; i < n; i++ { xv := x[i] * alpha - sum := a[offset] * x[i] - atmp := a[offset+1 : offset+n-i] + sum := ap[offset] * x[i] + atmp := ap[offset+1 : offset+n-i] xtmp := x[i+1:] jy := ky + (i+1)*incY for j, v := range atmp { @@ -1827,8 +2001,8 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ iy := ky for i := 0; i < n; i++ { xv := x[ix] * alpha - sum := a[offset] * x[ix] - atmp := a[offset+1 : offset+n-i] + sum := ap[offset] * x[ix] + atmp := ap[offset+1 : offset+n-i] jx := kx + (i+1)*incX jy := ky + (i+1)*incY for _, v := range atmp { @@ -1848,7 +2022,7 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ iy := ky for i := 0; i < n; i++ { xv := x[i] * alpha - atmp := a[offset-i : offset] + atmp := ap[offset-i : offset] jy := ky var sum float64 for j, v := range atmp { @@ -1856,7 +2030,7 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ y[jy] += v * xv jy += incY } - sum += a[offset] * x[i] + sum += ap[offset] * x[i] y[iy] += alpha * sum iy += incY offset += i + 2 @@ -1867,7 +2041,7 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ iy := ky for i := 0; i < n; i++ { xv := x[ix] * alpha - atmp := a[offset-i : offset] + atmp := ap[offset-i : offset] jx := kx jy := ky var sum float64 @@ -1878,7 +2052,7 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ jy += incY } - sum += a[offset] * x[ix] + sum += ap[offset] * x[ix] y[iy] += alpha * sum ix += incX iy += incY @@ -1890,7 +2064,7 @@ func (Implementation) Dspmv(ul blas.Uplo, n int, alpha float64, a []float64, x [ // 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) { +func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX int, ap []float64) { if ul != blas.Lower && ul != blas.Upper { panic(badUplo) } @@ -1900,15 +2074,25 @@ func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX 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 { + + // Quick return if possible. + if n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) + } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. + if alpha == 0 { + return + } + lenX := n var kx int if incX < 0 { @@ -1918,7 +2102,7 @@ func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX if ul == blas.Upper { if incX == 1 { for i := 0; i < n; i++ { - atmp := a[offset:] + atmp := ap[offset:] xv := alpha * x[i] xtmp := x[i:n] for j, v := range xtmp { @@ -1931,7 +2115,7 @@ func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX ix := kx for i := 0; i < n; i++ { jx := kx + i*incX - atmp := a[offset:] + atmp := ap[offset:] xv := alpha * x[ix] for j := 0; j < n-i; j++ { atmp[j] += xv * x[jx] @@ -1944,7 +2128,7 @@ func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX } if incX == 1 { for i := 0; i < n; i++ { - atmp := a[offset-i:] + atmp := ap[offset-i:] xv := alpha * x[i] xtmp := x[:i+1] for j, v := range xtmp { @@ -1957,7 +2141,7 @@ func (Implementation) Dspr(ul blas.Uplo, n int, alpha float64, x []float64, incX ix := kx for i := 0; i < n; i++ { jx := kx - atmp := a[offset-i:] + atmp := ap[offset-i:] xv := alpha * x[ix] for j := 0; j <= i; j++ { atmp[j] += xv * x[jx] @@ -1985,18 +2169,28 @@ func (Implementation) Dspr2(ul blas.Uplo, n int, alpha float64, x []float64, inc if incY == 0 { panic(zeroIncY) } - 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 (incY > 0 && (n-1)*incY >= len(y)) || (incY < 0 && (1-n)*incY >= len(y)) { - panic(badY) + + // For zero matrix size the following slice length checks are trivially satisfied. + if (incX > 0 && len(x) <= (n-1)*incX) || (incX < 0 && len(x) <= (1-n)*incX) { + panic(shortX) } - if len(ap) < (n*(n+1))/2 { - panic(badLdA) + if (incY > 0 && len(y) <= (n-1)*incY) || (incY < 0 && len(y) <= (1-n)*incY) { + panic(shortY) } + if len(ap) < n*(n+1)/2 { + panic(shortAP) + } + + // Quick return if possible. if alpha == 0 { return } + var ky, kx int if incY < 0 { ky = -(n - 1) * incY diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go new file mode 100644 index 00000000000..e4a2bb5e9b0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx128.go @@ -0,0 +1,1715 @@ +// Copyright ©2019 The Gonum Authors. 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/cmplx" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/c128" +) + +var _ blas.Complex128Level3 = Implementation{} + +// Zgemm 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 or op(X) = X^H, +// alpha and beta are scalars, and A, B and C are matrices, with op(A) an m×k matrix, +// op(B) a k×n matrix and C an m×n matrix. +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) { + switch tA { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch tB { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + } + rowA, colA := m, k + if tA != blas.NoTrans { + rowA, colA = k, m + } + if lda < max(1, colA) { + panic(badLdA) + } + rowB, colB := k, n + if tB != blas.NoTrans { + rowB, colB = n, k + } + if ldb < max(1, colB) { + panic(badLdB) + } + if ldc < max(1, n) { + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (rowA-1)*lda+colA { + panic(shortA) + } + if len(b) < (rowB-1)*ldb+colB { + panic(shortB) + } + if len(c) < (m-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + } + return + } + + switch tA { + case blas.NoTrans: + switch tB { + case blas.NoTrans: + // Form C = alpha * A * B + beta * C. + for i := 0; i < m; i++ { + switch { + case beta == 0: + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + case beta != 1: + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[i*lda+l] + for j := 0; j < n; j++ { + c[i*ldc+j] += tmp * b[l*ldb+j] + } + } + } + case blas.Trans: + // Form C = alpha * A * B^T + beta * C. + for i := 0; i < m; i++ { + switch { + case beta == 0: + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + case beta != 1: + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[i*lda+l] + for j := 0; j < n; j++ { + c[i*ldc+j] += tmp * b[j*ldb+l] + } + } + } + case blas.ConjTrans: + // Form C = alpha * A * B^H + beta * C. + for i := 0; i < m; i++ { + switch { + case beta == 0: + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + case beta != 1: + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[i*lda+l] + for j := 0; j < n; j++ { + c[i*ldc+j] += tmp * cmplx.Conj(b[j*ldb+l]) + } + } + } + } + case blas.Trans: + switch tB { + case blas.NoTrans: + // Form C = alpha * A^T * B + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex128 + for l := 0; l < k; l++ { + tmp += a[l*lda+i] * b[l*ldb+j] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.Trans: + // Form C = alpha * A^T * B^T + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex128 + for l := 0; l < k; l++ { + tmp += a[l*lda+i] * b[j*ldb+l] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.ConjTrans: + // Form C = alpha * A^T * B^H + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex128 + for l := 0; l < k; l++ { + tmp += a[l*lda+i] * cmplx.Conj(b[j*ldb+l]) + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + case blas.ConjTrans: + switch tB { + case blas.NoTrans: + // Form C = alpha * A^H * B + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex128 + for l := 0; l < k; l++ { + tmp += cmplx.Conj(a[l*lda+i]) * b[l*ldb+j] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.Trans: + // Form C = alpha * A^H * B^T + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex128 + for l := 0; l < k; l++ { + tmp += cmplx.Conj(a[l*lda+i]) * b[j*ldb+l] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.ConjTrans: + // Form C = alpha * A^H * B^H + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex128 + for l := 0; l < k; l++ { + tmp += cmplx.Conj(a[l*lda+i]) * cmplx.Conj(b[j*ldb+l]) + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + } +} + +// Zhemm performs one of the matrix-matrix operations +// C = alpha*A*B + beta*C if side == blas.Left +// C = alpha*B*A + beta*C if side == blas.Right +// where alpha and beta are scalars, A is an m×m or n×n hermitian matrix and B +// and C are m×n matrices. The imaginary parts of the diagonal elements of A are +// assumed to be zero. +func (Implementation) Zhemm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(na-1)+na { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if len(c) < ldc*(m-1)+n { + panic(shortC) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + c128.ScalUnitary(beta, ci) + } + } + return + } + + if side == blas.Left { + // Form C = alpha*A*B + beta*C. + for i := 0; i < m; i++ { + atmp := alpha * complex(real(a[i*lda+i]), 0) + bi := b[i*ldb : i*ldb+n] + ci := c[i*ldc : i*ldc+n] + if beta == 0 { + for j, bij := range bi { + ci[j] = atmp * bij + } + } else { + for j, bij := range bi { + ci[j] = atmp*bij + beta*ci[j] + } + } + if uplo == blas.Upper { + for k := 0; k < i; k++ { + atmp = alpha * cmplx.Conj(a[k*lda+i]) + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * a[i*lda+k] + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } else { + for k := 0; k < i; k++ { + atmp = alpha * a[i*lda+k] + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * cmplx.Conj(a[k*lda+i]) + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } + } + } else { + // Form C = alpha*B*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + abij := alpha * b[i*ldb+j] + aj := a[j*lda+j+1 : j*lda+n] + bi := b[i*ldb+j+1 : i*ldb+n] + ci := c[i*ldc+j+1 : i*ldc+n] + var tmp complex128 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * cmplx.Conj(ajk) + } + ajj := complex(real(a[j*lda+j]), 0) + if beta == 0 { + c[i*ldc+j] = abij*ajj + alpha*tmp + } else { + c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + abij := alpha * b[i*ldb+j] + aj := a[j*lda : j*lda+j] + bi := b[i*ldb : i*ldb+j] + ci := c[i*ldc : i*ldc+j] + var tmp complex128 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * cmplx.Conj(ajk) + } + ajj := complex(real(a[j*lda+j]), 0) + if beta == 0 { + c[i*ldc+j] = abij*ajj + alpha*tmp + } else { + c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + } +} + +// Zherk performs one of the hermitian rank-k operations +// C = alpha*A*A^H + beta*C if trans == blas.NoTrans +// C = alpha*A^H*A + beta*C if trans == blas.ConjTrans +// where alpha and beta are real scalars, C is an n×n hermitian matrix and A is +// an n×k matrix in the first case and a k×n matrix in the second case. +// +// The imaginary parts of the diagonal elements of C are assumed to be zero, and +// on return they will be set to zero. +func (Implementation) Zherk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha float64, a []complex128, lda int, beta float64, c []complex128, ldc int) { + var rowA, colA int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + rowA, colA = n, k + case blas.ConjTrans: + rowA, colA = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, colA): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (rowA-1)*lda+colA { + panic(shortA) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ci[0] = complex(beta*real(ci[0]), 0) + if i != n-1 { + c128.DscalUnitary(beta, ci[1:]) + } + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + if i != 0 { + c128.DscalUnitary(beta, ci[:i]) + } + ci[i] = complex(beta*real(ci[i]), 0) + } + } + } + return + } + + calpha := complex(alpha, 0) + if trans == blas.NoTrans { + // Form C = alpha*A*A^H + beta*C. + cbeta := complex(beta, 0) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ai := a[i*lda : i*lda+k] + switch { + case beta == 0: + // Handle the i-th diagonal element of C. + ci[0] = complex(alpha*real(c128.DotcUnitary(ai, ai)), 0) + // Handle the remaining elements on the i-th row of C. + for jc := range ci[1:] { + j := i + 1 + jc + ci[jc+1] = calpha * c128.DotcUnitary(a[j*lda:j*lda+k], ai) + } + case beta != 1: + cii := calpha*c128.DotcUnitary(ai, ai) + cbeta*ci[0] + ci[0] = complex(real(cii), 0) + for jc, cij := range ci[1:] { + j := i + 1 + jc + ci[jc+1] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij + } + default: + cii := calpha*c128.DotcUnitary(ai, ai) + ci[0] + ci[0] = complex(real(cii), 0) + for jc, cij := range ci[1:] { + j := i + 1 + jc + ci[jc+1] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cij + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + ai := a[i*lda : i*lda+k] + switch { + case beta == 0: + // Handle the first i-1 elements on the i-th row of C. + for j := range ci[:i] { + ci[j] = calpha * c128.DotcUnitary(a[j*lda:j*lda+k], ai) + } + // Handle the i-th diagonal element of C. + ci[i] = complex(alpha*real(c128.DotcUnitary(ai, ai)), 0) + case beta != 1: + for j, cij := range ci[:i] { + ci[j] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij + } + cii := calpha*c128.DotcUnitary(ai, ai) + cbeta*ci[i] + ci[i] = complex(real(cii), 0) + default: + for j, cij := range ci[:i] { + ci[j] = calpha*c128.DotcUnitary(a[j*lda:j*lda+k], ai) + cij + } + cii := calpha*c128.DotcUnitary(ai, ai) + ci[i] + ci[i] = complex(real(cii), 0) + } + } + } + } else { + // Form C = alpha*A^H*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + c128.DscalUnitary(beta, ci) + ci[0] = complex(real(ci[0]), 0) + default: + ci[0] = complex(real(ci[0]), 0) + } + for j := 0; j < k; j++ { + aji := cmplx.Conj(a[j*lda+i]) + if aji != 0 { + c128.AxpyUnitary(calpha*aji, a[j*lda+i:j*lda+n], ci) + } + } + c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + c128.DscalUnitary(beta, ci) + ci[i] = complex(real(ci[i]), 0) + default: + ci[i] = complex(real(ci[i]), 0) + } + for j := 0; j < k; j++ { + aji := cmplx.Conj(a[j*lda+i]) + if aji != 0 { + c128.AxpyUnitary(calpha*aji, a[j*lda:j*lda+i+1], ci) + } + } + c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) + } + } + } +} + +// Zher2k performs one of the hermitian rank-2k operations +// C = alpha*A*B^H + conj(alpha)*B*A^H + beta*C if trans == blas.NoTrans +// C = alpha*A^H*B + conj(alpha)*B^H*A + beta*C if trans == blas.ConjTrans +// where alpha and beta are scalars with beta real, C is an n×n hermitian matrix +// and A and B are n×k matrices in the first case and k×n matrices in the second case. +// +// The imaginary parts of the diagonal elements of C are assumed to be zero, and +// on return they will be set to zero. +func (Implementation) Zher2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta float64, c []complex128, ldc int) { + var row, col int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + row, col = n, k + case blas.ConjTrans: + row, col = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, col): + panic(badLdA) + case ldb < max(1, col): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (row-1)*lda+col { + panic(shortA) + } + if len(b) < (row-1)*ldb+col { + panic(shortB) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ci[0] = complex(beta*real(ci[0]), 0) + if i != n-1 { + c128.DscalUnitary(beta, ci[1:]) + } + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + if i != 0 { + c128.DscalUnitary(beta, ci[:i]) + } + ci[i] = complex(beta*real(ci[i]), 0) + } + } + } + return + } + + conjalpha := cmplx.Conj(alpha) + cbeta := complex(beta, 0) + if trans == blas.NoTrans { + // Form C = alpha*A*B^H + conj(alpha)*B*A^H + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i+1 : i*ldc+n] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) + c[i*ldc+i] = complex(real(cii), 0) + for jc := range ci { + j := i + 1 + jc + ci[jc] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) + } + } else { + cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] + c[i*ldc+i] = complex(real(cii), 0) + for jc, cij := range ci { + j := i + 1 + jc + ci[jc] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + for j := range ci { + ci[j] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) + } + cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) + c[i*ldc+i] = complex(real(cii), 0) + } else { + for j, cij := range ci { + ci[j] = alpha*c128.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c128.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij + } + cii := alpha*c128.DotcUnitary(bi, ai) + conjalpha*c128.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] + c[i*ldc+i] = complex(real(cii), 0) + } + } + } + } else { + // Form C = alpha*A^H*B + conj(alpha)*B^H*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + c128.DscalUnitary(beta, ci) + ci[0] = complex(real(ci[0]), 0) + default: + ci[0] = complex(real(ci[0]), 0) + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c128.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb+i:j*ldb+n], ci) + } + if bji != 0 { + c128.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda+i:j*lda+n], ci) + } + } + ci[0] = complex(real(ci[0]), 0) + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + c128.DscalUnitary(beta, ci) + ci[i] = complex(real(ci[i]), 0) + default: + ci[i] = complex(real(ci[i]), 0) + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c128.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb:j*ldb+i+1], ci) + } + if bji != 0 { + c128.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda:j*lda+i+1], ci) + } + } + ci[i] = complex(real(ci[i]), 0) + } + } + } +} + +// Zsymm performs one of the matrix-matrix operations +// C = alpha*A*B + beta*C if side == blas.Left +// C = alpha*B*A + beta*C if side == blas.Right +// where alpha and beta are scalars, A is an m×m or n×n symmetric matrix and B +// and C are m×n matrices. +func (Implementation) Zsymm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(na-1)+na { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if len(c) < ldc*(m-1)+n { + panic(shortC) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + c128.ScalUnitary(beta, ci) + } + } + return + } + + if side == blas.Left { + // Form C = alpha*A*B + beta*C. + for i := 0; i < m; i++ { + atmp := alpha * a[i*lda+i] + bi := b[i*ldb : i*ldb+n] + ci := c[i*ldc : i*ldc+n] + if beta == 0 { + for j, bij := range bi { + ci[j] = atmp * bij + } + } else { + for j, bij := range bi { + ci[j] = atmp*bij + beta*ci[j] + } + } + if uplo == blas.Upper { + for k := 0; k < i; k++ { + atmp = alpha * a[k*lda+i] + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * a[i*lda+k] + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } else { + for k := 0; k < i; k++ { + atmp = alpha * a[i*lda+k] + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * a[k*lda+i] + c128.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } + } + } else { + // Form C = alpha*B*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + abij := alpha * b[i*ldb+j] + aj := a[j*lda+j+1 : j*lda+n] + bi := b[i*ldb+j+1 : i*ldb+n] + ci := c[i*ldc+j+1 : i*ldc+n] + var tmp complex128 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * ajk + } + if beta == 0 { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + } else { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + abij := alpha * b[i*ldb+j] + aj := a[j*lda : j*lda+j] + bi := b[i*ldb : i*ldb+j] + ci := c[i*ldc : i*ldc+j] + var tmp complex128 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * ajk + } + if beta == 0 { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + } else { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + } +} + +// Zsyrk performs one of the symmetric rank-k operations +// C = alpha*A*A^T + beta*C if trans == blas.NoTrans +// C = alpha*A^T*A + beta*C if trans == blas.Trans +// where alpha and beta are scalars, C is an n×n symmetric matrix and A is +// an n×k matrix in the first case and a k×n matrix in the second case. +func (Implementation) Zsyrk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, beta complex128, c []complex128, ldc int) { + var rowA, colA int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + rowA, colA = n, k + case blas.Trans: + rowA, colA = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, colA): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (rowA-1)*lda+colA { + panic(shortA) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + c128.ScalUnitary(beta, ci) + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + c128.ScalUnitary(beta, ci) + } + } + } + return + } + + if trans == blas.NoTrans { + // Form C = alpha*A*A^T + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ai := a[i*lda : i*lda+k] + for jc, cij := range ci { + j := i + jc + ci[jc] = beta*cij + alpha*c128.DotuUnitary(ai, a[j*lda:j*lda+k]) + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + ai := a[i*lda : i*lda+k] + for j, cij := range ci { + ci[j] = beta*cij + alpha*c128.DotuUnitary(ai, a[j*lda:j*lda+k]) + } + } + } + } else { + // Form C = alpha*A^T*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + for jc := range ci { + ci[jc] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + if aji != 0 { + c128.AxpyUnitary(alpha*aji, a[j*lda+i:j*lda+n], ci) + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + for j := range ci { + ci[j] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + if aji != 0 { + c128.AxpyUnitary(alpha*aji, a[j*lda:j*lda+i+1], ci) + } + } + } + } + } +} + +// Zsyr2k performs one of the symmetric rank-2k operations +// C = alpha*A*B^T + alpha*B*A^T + beta*C if trans == blas.NoTrans +// C = alpha*A^T*B + alpha*B^T*A + beta*C if trans == blas.Trans +// where alpha and beta are scalars, C is an n×n symmetric matrix and A and B +// are n×k matrices in the first case and k×n matrices in the second case. +func (Implementation) Zsyr2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex128, a []complex128, lda int, b []complex128, ldb int, beta complex128, c []complex128, ldc int) { + var row, col int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + row, col = n, k + case blas.Trans: + row, col = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, col): + panic(badLdA) + case ldb < max(1, col): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (row-1)*lda+col { + panic(shortA) + } + if len(b) < (row-1)*ldb+col { + panic(shortB) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + c128.ScalUnitary(beta, ci) + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + c128.ScalUnitary(beta, ci) + } + } + } + return + } + + if trans == blas.NoTrans { + // Form C = alpha*A*B^T + alpha*B*A^T + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + for jc := range ci { + j := i + jc + ci[jc] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) + } + } else { + for jc, cij := range ci { + j := i + jc + ci[jc] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + for j := range ci { + ci[j] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) + } + } else { + for j, cij := range ci { + ci[j] = alpha*c128.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c128.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij + } + } + } + } + } else { + // Form C = alpha*A^T*B + alpha*B^T*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + for jc := range ci { + ci[jc] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c128.AxpyUnitary(alpha*aji, b[j*ldb+i:j*ldb+n], ci) + } + if bji != 0 { + c128.AxpyUnitary(alpha*bji, a[j*lda+i:j*lda+n], ci) + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + for j := range ci { + ci[j] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c128.AxpyUnitary(alpha*aji, b[j*ldb:j*ldb+i+1], ci) + } + if bji != 0 { + c128.AxpyUnitary(alpha*bji, a[j*lda:j*lda+i+1], ci) + } + } + } + } + } +} + +// Ztrmm performs one of the matrix-matrix operations +// B = alpha * op(A) * B if side == blas.Left, +// B = alpha * B * op(A) if side == blas.Right, +// where alpha is a scalar, B is an m×n matrix, A is a unit, or non-unit, +// upper or lower triangular matrix and op(A) is one of +// op(A) = A if trans == blas.NoTrans, +// op(A) = A^T if trans == blas.Trans, +// op(A) = A^H if trans == blas.ConjTrans. +func (Implementation) Ztrmm(side blas.Side, uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: + panic(badTranspose) + case diag != blas.Unit && diag != blas.NonUnit: + panic(badDiag) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (na-1)*lda+na { + panic(shortA) + } + if len(b) < (m-1)*ldb+n { + panic(shortB) + } + + // Quick return if possible. + if alpha == 0 { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j := range bi { + bi[j] = 0 + } + } + return + } + + noConj := trans != blas.ConjTrans + noUnit := diag == blas.NonUnit + if side == blas.Left { + if trans == blas.NoTrans { + // Form B = alpha*A*B. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + aii := alpha + if noUnit { + aii *= a[i*lda+i] + } + bi := b[i*ldb : i*ldb+n] + for j := range bi { + bi[j] *= aii + } + for ja, aij := range a[i*lda+i+1 : i*lda+m] { + j := ja + i + 1 + if aij != 0 { + c128.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) + } + } + } + } else { + for i := m - 1; i >= 0; i-- { + aii := alpha + if noUnit { + aii *= a[i*lda+i] + } + bi := b[i*ldb : i*ldb+n] + for j := range bi { + bi[j] *= aii + } + for j, aij := range a[i*lda : i*lda+i] { + if aij != 0 { + c128.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) + } + } + } + } + } else { + // Form B = alpha*A^T*B or B = alpha*A^H*B. + if uplo == blas.Upper { + for k := m - 1; k >= 0; k-- { + bk := b[k*ldb : k*ldb+n] + for ja, ajk := range a[k*lda+k+1 : k*lda+m] { + if ajk == 0 { + continue + } + j := k + 1 + ja + if noConj { + c128.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) + } else { + c128.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) + } + } + akk := alpha + if noUnit { + if noConj { + akk *= a[k*lda+k] + } else { + akk *= cmplx.Conj(a[k*lda+k]) + } + } + if akk != 1 { + c128.ScalUnitary(akk, bk) + } + } + } else { + for k := 0; k < m; k++ { + bk := b[k*ldb : k*ldb+n] + for j, ajk := range a[k*lda : k*lda+k] { + if ajk == 0 { + continue + } + if noConj { + c128.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) + } else { + c128.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) + } + } + akk := alpha + if noUnit { + if noConj { + akk *= a[k*lda+k] + } else { + akk *= cmplx.Conj(a[k*lda+k]) + } + } + if akk != 1 { + c128.ScalUnitary(akk, bk) + } + } + } + } + } else { + if trans == blas.NoTrans { + // Form B = alpha*B*A. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for k := n - 1; k >= 0; k-- { + abik := alpha * bi[k] + if abik == 0 { + continue + } + bi[k] = abik + if noUnit { + bi[k] *= a[k*lda+k] + } + c128.AxpyUnitary(abik, a[k*lda+k+1:k*lda+n], bi[k+1:]) + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for k := 0; k < n; k++ { + abik := alpha * bi[k] + if abik == 0 { + continue + } + bi[k] = abik + if noUnit { + bi[k] *= a[k*lda+k] + } + c128.AxpyUnitary(abik, a[k*lda:k*lda+k], bi[:k]) + } + } + } + } else { + // Form B = alpha*B*A^T or B = alpha*B*A^H. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j, bij := range bi { + if noConj { + if noUnit { + bij *= a[j*lda+j] + } + bij += c128.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + } else { + if noUnit { + bij *= cmplx.Conj(a[j*lda+j]) + } + bij += c128.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + } + bi[j] = alpha * bij + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + bij := bi[j] + if noConj { + if noUnit { + bij *= a[j*lda+j] + } + bij += c128.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) + } else { + if noUnit { + bij *= cmplx.Conj(a[j*lda+j]) + } + bij += c128.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) + } + bi[j] = alpha * bij + } + } + } + } + } +} + +// Ztrsm solves one of the matrix equations +// op(A) * X = alpha * B if side == blas.Left, +// X * op(A) = alpha * B if side == blas.Right, +// where alpha is a scalar, X and B are m×n matrices, A is a unit or +// non-unit, upper or lower triangular matrix and op(A) is one of +// op(A) = A if transA == blas.NoTrans, +// op(A) = A^T if transA == blas.Trans, +// op(A) = A^H if transA == blas.ConjTrans. +// On return the matrix X is overwritten on B. +func (Implementation) Ztrsm(side blas.Side, uplo blas.Uplo, transA blas.Transpose, diag blas.Diag, m, n int, alpha complex128, a []complex128, lda int, b []complex128, ldb int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case transA != blas.NoTrans && transA != blas.Trans && transA != blas.ConjTrans: + panic(badTranspose) + case diag != blas.Unit && diag != blas.NonUnit: + panic(badDiag) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (na-1)*lda+na { + panic(shortA) + } + if len(b) < (m-1)*ldb+n { + panic(shortB) + } + + if alpha == 0 { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + b[i*ldb+j] = 0 + } + } + return + } + + noConj := transA != blas.ConjTrans + noUnit := diag == blas.NonUnit + if side == blas.Left { + if transA == blas.NoTrans { + // Form B = alpha*inv(A)*B. + if uplo == blas.Upper { + for i := m - 1; i >= 0; i-- { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c128.ScalUnitary(alpha, bi) + } + for ka, aik := range a[i*lda+i+1 : i*lda+m] { + k := i + 1 + ka + if aik != 0 { + c128.AxpyUnitary(-aik, b[k*ldb:k*ldb+n], bi) + } + } + if noUnit { + c128.ScalUnitary(1/a[i*lda+i], bi) + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c128.ScalUnitary(alpha, bi) + } + for j, aij := range a[i*lda : i*lda+i] { + if aij != 0 { + c128.AxpyUnitary(-aij, b[j*ldb:j*ldb+n], bi) + } + } + if noUnit { + c128.ScalUnitary(1/a[i*lda+i], bi) + } + } + } + } else { + // Form B = alpha*inv(A^T)*B or B = alpha*inv(A^H)*B. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if noUnit { + if noConj { + c128.ScalUnitary(1/a[i*lda+i], bi) + } else { + c128.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) + } + } + for ja, aij := range a[i*lda+i+1 : i*lda+m] { + if aij == 0 { + continue + } + j := i + 1 + ja + if noConj { + c128.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) + } else { + c128.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) + } + } + if alpha != 1 { + c128.ScalUnitary(alpha, bi) + } + } + } else { + for i := m - 1; i >= 0; i-- { + bi := b[i*ldb : i*ldb+n] + if noUnit { + if noConj { + c128.ScalUnitary(1/a[i*lda+i], bi) + } else { + c128.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) + } + } + for j, aij := range a[i*lda : i*lda+i] { + if aij == 0 { + continue + } + if noConj { + c128.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) + } else { + c128.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) + } + } + if alpha != 1 { + c128.ScalUnitary(alpha, bi) + } + } + } + } + } else { + if transA == blas.NoTrans { + // Form B = alpha*B*inv(A). + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c128.ScalUnitary(alpha, bi) + } + for j, bij := range bi { + if bij == 0 { + continue + } + if noUnit { + bi[j] /= a[j*lda+j] + } + c128.AxpyUnitary(-bi[j], a[j*lda+j+1:j*lda+n], bi[j+1:n]) + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c128.ScalUnitary(alpha, bi) + } + for j := n - 1; j >= 0; j-- { + if bi[j] == 0 { + continue + } + if noUnit { + bi[j] /= a[j*lda+j] + } + c128.AxpyUnitary(-bi[j], a[j*lda:j*lda+j], bi[:j]) + } + } + } + } else { + // Form B = alpha*B*inv(A^T) or B = alpha*B*inv(A^H). + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + bij := alpha * bi[j] + if noConj { + bij -= c128.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + if noUnit { + bij /= a[j*lda+j] + } + } else { + bij -= c128.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + if noUnit { + bij /= cmplx.Conj(a[j*lda+j]) + } + } + bi[j] = bij + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j, bij := range bi { + bij *= alpha + if noConj { + bij -= c128.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) + if noUnit { + bij /= a[j*lda+j] + } + } else { + bij -= c128.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) + if noUnit { + bij /= cmplx.Conj(a[j*lda+j]) + } + } + bi[j] = bij + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go new file mode 100644 index 00000000000..436c545065a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3cmplx64.go @@ -0,0 +1,1735 @@ +// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT. + +// Copyright ©2019 The Gonum Authors. 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 ( + cmplx "gonum.org/v1/gonum/internal/cmplx64" + + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/internal/asm/c64" +) + +var _ blas.Complex64Level3 = Implementation{} + +// Cgemm 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 or op(X) = X^H, +// alpha and beta are scalars, and A, B and C are matrices, with op(A) an m×k matrix, +// op(B) a k×n matrix and C an m×n matrix. +// +// Complex64 implementations are autogenerated and not directly tested. +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) { + switch tA { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch tB { + default: + panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + } + rowA, colA := m, k + if tA != blas.NoTrans { + rowA, colA = k, m + } + if lda < max(1, colA) { + panic(badLdA) + } + rowB, colB := k, n + if tB != blas.NoTrans { + rowB, colB = n, k + } + if ldb < max(1, colB) { + panic(badLdB) + } + if ldc < max(1, n) { + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (rowA-1)*lda+colA { + panic(shortA) + } + if len(b) < (rowB-1)*ldb+colB { + panic(shortB) + } + if len(c) < (m-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + } + return + } + + switch tA { + case blas.NoTrans: + switch tB { + case blas.NoTrans: + // Form C = alpha * A * B + beta * C. + for i := 0; i < m; i++ { + switch { + case beta == 0: + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + case beta != 1: + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[i*lda+l] + for j := 0; j < n; j++ { + c[i*ldc+j] += tmp * b[l*ldb+j] + } + } + } + case blas.Trans: + // Form C = alpha * A * B^T + beta * C. + for i := 0; i < m; i++ { + switch { + case beta == 0: + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + case beta != 1: + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[i*lda+l] + for j := 0; j < n; j++ { + c[i*ldc+j] += tmp * b[j*ldb+l] + } + } + } + case blas.ConjTrans: + // Form C = alpha * A * B^H + beta * C. + for i := 0; i < m; i++ { + switch { + case beta == 0: + for j := 0; j < n; j++ { + c[i*ldc+j] = 0 + } + case beta != 1: + for j := 0; j < n; j++ { + c[i*ldc+j] *= beta + } + } + for l := 0; l < k; l++ { + tmp := alpha * a[i*lda+l] + for j := 0; j < n; j++ { + c[i*ldc+j] += tmp * cmplx.Conj(b[j*ldb+l]) + } + } + } + } + case blas.Trans: + switch tB { + case blas.NoTrans: + // Form C = alpha * A^T * B + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex64 + for l := 0; l < k; l++ { + tmp += a[l*lda+i] * b[l*ldb+j] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.Trans: + // Form C = alpha * A^T * B^T + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex64 + for l := 0; l < k; l++ { + tmp += a[l*lda+i] * b[j*ldb+l] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.ConjTrans: + // Form C = alpha * A^T * B^H + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex64 + for l := 0; l < k; l++ { + tmp += a[l*lda+i] * cmplx.Conj(b[j*ldb+l]) + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + case blas.ConjTrans: + switch tB { + case blas.NoTrans: + // Form C = alpha * A^H * B + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex64 + for l := 0; l < k; l++ { + tmp += cmplx.Conj(a[l*lda+i]) * b[l*ldb+j] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.Trans: + // Form C = alpha * A^H * B^T + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex64 + for l := 0; l < k; l++ { + tmp += cmplx.Conj(a[l*lda+i]) * b[j*ldb+l] + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + case blas.ConjTrans: + // Form C = alpha * A^H * B^H + beta * C. + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + var tmp complex64 + for l := 0; l < k; l++ { + tmp += cmplx.Conj(a[l*lda+i]) * cmplx.Conj(b[j*ldb+l]) + } + if beta == 0 { + c[i*ldc+j] = alpha * tmp + } else { + c[i*ldc+j] = alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + } +} + +// Chemm performs one of the matrix-matrix operations +// C = alpha*A*B + beta*C if side == blas.Left +// C = alpha*B*A + beta*C if side == blas.Right +// where alpha and beta are scalars, A is an m×m or n×n hermitian matrix and B +// and C are m×n matrices. The imaginary parts of the diagonal elements of A are +// assumed to be zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Chemm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(na-1)+na { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if len(c) < ldc*(m-1)+n { + panic(shortC) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + c64.ScalUnitary(beta, ci) + } + } + return + } + + if side == blas.Left { + // Form C = alpha*A*B + beta*C. + for i := 0; i < m; i++ { + atmp := alpha * complex(real(a[i*lda+i]), 0) + bi := b[i*ldb : i*ldb+n] + ci := c[i*ldc : i*ldc+n] + if beta == 0 { + for j, bij := range bi { + ci[j] = atmp * bij + } + } else { + for j, bij := range bi { + ci[j] = atmp*bij + beta*ci[j] + } + } + if uplo == blas.Upper { + for k := 0; k < i; k++ { + atmp = alpha * cmplx.Conj(a[k*lda+i]) + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * a[i*lda+k] + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } else { + for k := 0; k < i; k++ { + atmp = alpha * a[i*lda+k] + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * cmplx.Conj(a[k*lda+i]) + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } + } + } else { + // Form C = alpha*B*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + abij := alpha * b[i*ldb+j] + aj := a[j*lda+j+1 : j*lda+n] + bi := b[i*ldb+j+1 : i*ldb+n] + ci := c[i*ldc+j+1 : i*ldc+n] + var tmp complex64 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * cmplx.Conj(ajk) + } + ajj := complex(real(a[j*lda+j]), 0) + if beta == 0 { + c[i*ldc+j] = abij*ajj + alpha*tmp + } else { + c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + abij := alpha * b[i*ldb+j] + aj := a[j*lda : j*lda+j] + bi := b[i*ldb : i*ldb+j] + ci := c[i*ldc : i*ldc+j] + var tmp complex64 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * cmplx.Conj(ajk) + } + ajj := complex(real(a[j*lda+j]), 0) + if beta == 0 { + c[i*ldc+j] = abij*ajj + alpha*tmp + } else { + c[i*ldc+j] = abij*ajj + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + } +} + +// Cherk performs one of the hermitian rank-k operations +// C = alpha*A*A^H + beta*C if trans == blas.NoTrans +// C = alpha*A^H*A + beta*C if trans == blas.ConjTrans +// where alpha and beta are real scalars, C is an n×n hermitian matrix and A is +// an n×k matrix in the first case and a k×n matrix in the second case. +// +// The imaginary parts of the diagonal elements of C are assumed to be zero, and +// on return they will be set to zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cherk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha float32, a []complex64, lda int, beta float32, c []complex64, ldc int) { + var rowA, colA int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + rowA, colA = n, k + case blas.ConjTrans: + rowA, colA = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, colA): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (rowA-1)*lda+colA { + panic(shortA) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ci[0] = complex(beta*real(ci[0]), 0) + if i != n-1 { + c64.SscalUnitary(beta, ci[1:]) + } + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + if i != 0 { + c64.SscalUnitary(beta, ci[:i]) + } + ci[i] = complex(beta*real(ci[i]), 0) + } + } + } + return + } + + calpha := complex(alpha, 0) + if trans == blas.NoTrans { + // Form C = alpha*A*A^H + beta*C. + cbeta := complex(beta, 0) + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ai := a[i*lda : i*lda+k] + switch { + case beta == 0: + // Handle the i-th diagonal element of C. + ci[0] = complex(alpha*real(c64.DotcUnitary(ai, ai)), 0) + // Handle the remaining elements on the i-th row of C. + for jc := range ci[1:] { + j := i + 1 + jc + ci[jc+1] = calpha * c64.DotcUnitary(a[j*lda:j*lda+k], ai) + } + case beta != 1: + cii := calpha*c64.DotcUnitary(ai, ai) + cbeta*ci[0] + ci[0] = complex(real(cii), 0) + for jc, cij := range ci[1:] { + j := i + 1 + jc + ci[jc+1] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij + } + default: + cii := calpha*c64.DotcUnitary(ai, ai) + ci[0] + ci[0] = complex(real(cii), 0) + for jc, cij := range ci[1:] { + j := i + 1 + jc + ci[jc+1] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cij + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + ai := a[i*lda : i*lda+k] + switch { + case beta == 0: + // Handle the first i-1 elements on the i-th row of C. + for j := range ci[:i] { + ci[j] = calpha * c64.DotcUnitary(a[j*lda:j*lda+k], ai) + } + // Handle the i-th diagonal element of C. + ci[i] = complex(alpha*real(c64.DotcUnitary(ai, ai)), 0) + case beta != 1: + for j, cij := range ci[:i] { + ci[j] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cbeta*cij + } + cii := calpha*c64.DotcUnitary(ai, ai) + cbeta*ci[i] + ci[i] = complex(real(cii), 0) + default: + for j, cij := range ci[:i] { + ci[j] = calpha*c64.DotcUnitary(a[j*lda:j*lda+k], ai) + cij + } + cii := calpha*c64.DotcUnitary(ai, ai) + ci[i] + ci[i] = complex(real(cii), 0) + } + } + } + } else { + // Form C = alpha*A^H*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + c64.SscalUnitary(beta, ci) + ci[0] = complex(real(ci[0]), 0) + default: + ci[0] = complex(real(ci[0]), 0) + } + for j := 0; j < k; j++ { + aji := cmplx.Conj(a[j*lda+i]) + if aji != 0 { + c64.AxpyUnitary(calpha*aji, a[j*lda+i:j*lda+n], ci) + } + } + c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + c64.SscalUnitary(beta, ci) + ci[i] = complex(real(ci[i]), 0) + default: + ci[i] = complex(real(ci[i]), 0) + } + for j := 0; j < k; j++ { + aji := cmplx.Conj(a[j*lda+i]) + if aji != 0 { + c64.AxpyUnitary(calpha*aji, a[j*lda:j*lda+i+1], ci) + } + } + c[i*ldc+i] = complex(real(c[i*ldc+i]), 0) + } + } + } +} + +// Cher2k performs one of the hermitian rank-2k operations +// C = alpha*A*B^H + conj(alpha)*B*A^H + beta*C if trans == blas.NoTrans +// C = alpha*A^H*B + conj(alpha)*B^H*A + beta*C if trans == blas.ConjTrans +// where alpha and beta are scalars with beta real, C is an n×n hermitian matrix +// and A and B are n×k matrices in the first case and k×n matrices in the second case. +// +// The imaginary parts of the diagonal elements of C are assumed to be zero, and +// on return they will be set to zero. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Cher2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta float32, c []complex64, ldc int) { + var row, col int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + row, col = n, k + case blas.ConjTrans: + row, col = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, col): + panic(badLdA) + case ldb < max(1, col): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (row-1)*lda+col { + panic(shortA) + } + if len(b) < (row-1)*ldb+col { + panic(shortB) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ci[0] = complex(beta*real(ci[0]), 0) + if i != n-1 { + c64.SscalUnitary(beta, ci[1:]) + } + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + if i != 0 { + c64.SscalUnitary(beta, ci[:i]) + } + ci[i] = complex(beta*real(ci[i]), 0) + } + } + } + return + } + + conjalpha := cmplx.Conj(alpha) + cbeta := complex(beta, 0) + if trans == blas.NoTrans { + // Form C = alpha*A*B^H + conj(alpha)*B*A^H + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i+1 : i*ldc+n] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) + c[i*ldc+i] = complex(real(cii), 0) + for jc := range ci { + j := i + 1 + jc + ci[jc] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) + } + } else { + cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] + c[i*ldc+i] = complex(real(cii), 0) + for jc, cij := range ci { + j := i + 1 + jc + ci[jc] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + for j := range ci { + ci[j] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) + } + cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) + c[i*ldc+i] = complex(real(cii), 0) + } else { + for j, cij := range ci { + ci[j] = alpha*c64.DotcUnitary(b[j*ldb:j*ldb+k], ai) + conjalpha*c64.DotcUnitary(a[j*lda:j*lda+k], bi) + cbeta*cij + } + cii := alpha*c64.DotcUnitary(bi, ai) + conjalpha*c64.DotcUnitary(ai, bi) + cbeta*c[i*ldc+i] + c[i*ldc+i] = complex(real(cii), 0) + } + } + } + } else { + // Form C = alpha*A^H*B + conj(alpha)*B^H*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + c64.SscalUnitary(beta, ci) + ci[0] = complex(real(ci[0]), 0) + default: + ci[0] = complex(real(ci[0]), 0) + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c64.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb+i:j*ldb+n], ci) + } + if bji != 0 { + c64.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda+i:j*lda+n], ci) + } + } + ci[0] = complex(real(ci[0]), 0) + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + c64.SscalUnitary(beta, ci) + ci[i] = complex(real(ci[i]), 0) + default: + ci[i] = complex(real(ci[i]), 0) + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c64.AxpyUnitary(alpha*cmplx.Conj(aji), b[j*ldb:j*ldb+i+1], ci) + } + if bji != 0 { + c64.AxpyUnitary(conjalpha*cmplx.Conj(bji), a[j*lda:j*lda+i+1], ci) + } + } + ci[i] = complex(real(ci[i]), 0) + } + } + } +} + +// Csymm performs one of the matrix-matrix operations +// C = alpha*A*B + beta*C if side == blas.Left +// C = alpha*B*A + beta*C if side == blas.Right +// where alpha and beta are scalars, A is an m×m or n×n symmetric matrix and B +// and C are m×n matrices. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Csymm(side blas.Side, uplo blas.Uplo, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(na-1)+na { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if len(c) < ldc*(m-1)+n { + panic(shortC) + } + + // Quick return if possible. + if alpha == 0 && beta == 1 { + return + } + + if alpha == 0 { + if beta == 0 { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < m; i++ { + ci := c[i*ldc : i*ldc+n] + c64.ScalUnitary(beta, ci) + } + } + return + } + + if side == blas.Left { + // Form C = alpha*A*B + beta*C. + for i := 0; i < m; i++ { + atmp := alpha * a[i*lda+i] + bi := b[i*ldb : i*ldb+n] + ci := c[i*ldc : i*ldc+n] + if beta == 0 { + for j, bij := range bi { + ci[j] = atmp * bij + } + } else { + for j, bij := range bi { + ci[j] = atmp*bij + beta*ci[j] + } + } + if uplo == blas.Upper { + for k := 0; k < i; k++ { + atmp = alpha * a[k*lda+i] + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * a[i*lda+k] + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } else { + for k := 0; k < i; k++ { + atmp = alpha * a[i*lda+k] + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + for k := i + 1; k < m; k++ { + atmp = alpha * a[k*lda+i] + c64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ci) + } + } + } + } else { + // Form C = alpha*B*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + for j := n - 1; j >= 0; j-- { + abij := alpha * b[i*ldb+j] + aj := a[j*lda+j+1 : j*lda+n] + bi := b[i*ldb+j+1 : i*ldb+n] + ci := c[i*ldc+j+1 : i*ldc+n] + var tmp complex64 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * ajk + } + if beta == 0 { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + } else { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } else { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + abij := alpha * b[i*ldb+j] + aj := a[j*lda : j*lda+j] + bi := b[i*ldb : i*ldb+j] + ci := c[i*ldc : i*ldc+j] + var tmp complex64 + for k, ajk := range aj { + ci[k] += abij * ajk + tmp += bi[k] * ajk + } + if beta == 0 { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + } else { + c[i*ldc+j] = abij*a[j*lda+j] + alpha*tmp + beta*c[i*ldc+j] + } + } + } + } + } +} + +// Csyrk performs one of the symmetric rank-k operations +// C = alpha*A*A^T + beta*C if trans == blas.NoTrans +// C = alpha*A^T*A + beta*C if trans == blas.Trans +// where alpha and beta are scalars, C is an n×n symmetric matrix and A is +// an n×k matrix in the first case and a k×n matrix in the second case. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Csyrk(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, beta complex64, c []complex64, ldc int) { + var rowA, colA int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + rowA, colA = n, k + case blas.Trans: + rowA, colA = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, colA): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (rowA-1)*lda+colA { + panic(shortA) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + c64.ScalUnitary(beta, ci) + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + c64.ScalUnitary(beta, ci) + } + } + } + return + } + + if trans == blas.NoTrans { + // Form C = alpha*A*A^T + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ai := a[i*lda : i*lda+k] + for jc, cij := range ci { + j := i + jc + ci[jc] = beta*cij + alpha*c64.DotuUnitary(ai, a[j*lda:j*lda+k]) + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + ai := a[i*lda : i*lda+k] + for j, cij := range ci { + ci[j] = beta*cij + alpha*c64.DotuUnitary(ai, a[j*lda:j*lda+k]) + } + } + } + } else { + // Form C = alpha*A^T*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + for jc := range ci { + ci[jc] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + if aji != 0 { + c64.AxpyUnitary(alpha*aji, a[j*lda+i:j*lda+n], ci) + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + for j := range ci { + ci[j] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + if aji != 0 { + c64.AxpyUnitary(alpha*aji, a[j*lda:j*lda+i+1], ci) + } + } + } + } + } +} + +// Csyr2k performs one of the symmetric rank-2k operations +// C = alpha*A*B^T + alpha*B*A^T + beta*C if trans == blas.NoTrans +// C = alpha*A^T*B + alpha*B^T*A + beta*C if trans == blas.Trans +// where alpha and beta are scalars, C is an n×n symmetric matrix and A and B +// are n×k matrices in the first case and k×n matrices in the second case. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Csyr2k(uplo blas.Uplo, trans blas.Transpose, n, k int, alpha complex64, a []complex64, lda int, b []complex64, ldb int, beta complex64, c []complex64, ldc int) { + var row, col int + switch trans { + default: + panic(badTranspose) + case blas.NoTrans: + row, col = n, k + case blas.Trans: + row, col = k, n + } + switch { + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case lda < max(1, col): + panic(badLdA) + case ldb < max(1, col): + panic(badLdB) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (row-1)*lda+col { + panic(shortA) + } + if len(b) < (row-1)*ldb+col { + panic(shortB) + } + if len(c) < (n-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return + } + + if alpha == 0 { + if uplo == blas.Upper { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + c64.ScalUnitary(beta, ci) + } + } + } else { + if beta == 0 { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + for j := range ci { + ci[j] = 0 + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + c64.ScalUnitary(beta, ci) + } + } + } + return + } + + if trans == blas.NoTrans { + // Form C = alpha*A*B^T + alpha*B*A^T + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + for jc := range ci { + j := i + jc + ci[jc] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) + } + } else { + for jc, cij := range ci { + j := i + jc + ci[jc] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + ai := a[i*lda : i*lda+k] + bi := b[i*ldb : i*ldb+k] + if beta == 0 { + for j := range ci { + ci[j] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) + } + } else { + for j, cij := range ci { + ci[j] = alpha*c64.DotuUnitary(ai, b[j*ldb:j*ldb+k]) + alpha*c64.DotuUnitary(bi, a[j*lda:j*lda+k]) + beta*cij + } + } + } + } + } else { + // Form C = alpha*A^T*B + alpha*B^T*A + beta*C. + if uplo == blas.Upper { + for i := 0; i < n; i++ { + ci := c[i*ldc+i : i*ldc+n] + switch { + case beta == 0: + for jc := range ci { + ci[jc] = 0 + } + case beta != 1: + for jc := range ci { + ci[jc] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c64.AxpyUnitary(alpha*aji, b[j*ldb+i:j*ldb+n], ci) + } + if bji != 0 { + c64.AxpyUnitary(alpha*bji, a[j*lda+i:j*lda+n], ci) + } + } + } + } else { + for i := 0; i < n; i++ { + ci := c[i*ldc : i*ldc+i+1] + switch { + case beta == 0: + for j := range ci { + ci[j] = 0 + } + case beta != 1: + for j := range ci { + ci[j] *= beta + } + } + for j := 0; j < k; j++ { + aji := a[j*lda+i] + bji := b[j*ldb+i] + if aji != 0 { + c64.AxpyUnitary(alpha*aji, b[j*ldb:j*ldb+i+1], ci) + } + if bji != 0 { + c64.AxpyUnitary(alpha*bji, a[j*lda:j*lda+i+1], ci) + } + } + } + } + } +} + +// Ctrmm performs one of the matrix-matrix operations +// B = alpha * op(A) * B if side == blas.Left, +// B = alpha * B * op(A) if side == blas.Right, +// where alpha is a scalar, B is an m×n matrix, A is a unit, or non-unit, +// upper or lower triangular matrix and op(A) is one of +// op(A) = A if trans == blas.NoTrans, +// op(A) = A^T if trans == blas.Trans, +// op(A) = A^H if trans == blas.ConjTrans. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctrmm(side blas.Side, uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: + panic(badTranspose) + case diag != blas.Unit && diag != blas.NonUnit: + panic(badDiag) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (na-1)*lda+na { + panic(shortA) + } + if len(b) < (m-1)*ldb+n { + panic(shortB) + } + + // Quick return if possible. + if alpha == 0 { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j := range bi { + bi[j] = 0 + } + } + return + } + + noConj := trans != blas.ConjTrans + noUnit := diag == blas.NonUnit + if side == blas.Left { + if trans == blas.NoTrans { + // Form B = alpha*A*B. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + aii := alpha + if noUnit { + aii *= a[i*lda+i] + } + bi := b[i*ldb : i*ldb+n] + for j := range bi { + bi[j] *= aii + } + for ja, aij := range a[i*lda+i+1 : i*lda+m] { + j := ja + i + 1 + if aij != 0 { + c64.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) + } + } + } + } else { + for i := m - 1; i >= 0; i-- { + aii := alpha + if noUnit { + aii *= a[i*lda+i] + } + bi := b[i*ldb : i*ldb+n] + for j := range bi { + bi[j] *= aii + } + for j, aij := range a[i*lda : i*lda+i] { + if aij != 0 { + c64.AxpyUnitary(alpha*aij, b[j*ldb:j*ldb+n], bi) + } + } + } + } + } else { + // Form B = alpha*A^T*B or B = alpha*A^H*B. + if uplo == blas.Upper { + for k := m - 1; k >= 0; k-- { + bk := b[k*ldb : k*ldb+n] + for ja, ajk := range a[k*lda+k+1 : k*lda+m] { + if ajk == 0 { + continue + } + j := k + 1 + ja + if noConj { + c64.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) + } else { + c64.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) + } + } + akk := alpha + if noUnit { + if noConj { + akk *= a[k*lda+k] + } else { + akk *= cmplx.Conj(a[k*lda+k]) + } + } + if akk != 1 { + c64.ScalUnitary(akk, bk) + } + } + } else { + for k := 0; k < m; k++ { + bk := b[k*ldb : k*ldb+n] + for j, ajk := range a[k*lda : k*lda+k] { + if ajk == 0 { + continue + } + if noConj { + c64.AxpyUnitary(alpha*ajk, bk, b[j*ldb:j*ldb+n]) + } else { + c64.AxpyUnitary(alpha*cmplx.Conj(ajk), bk, b[j*ldb:j*ldb+n]) + } + } + akk := alpha + if noUnit { + if noConj { + akk *= a[k*lda+k] + } else { + akk *= cmplx.Conj(a[k*lda+k]) + } + } + if akk != 1 { + c64.ScalUnitary(akk, bk) + } + } + } + } + } else { + if trans == blas.NoTrans { + // Form B = alpha*B*A. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for k := n - 1; k >= 0; k-- { + abik := alpha * bi[k] + if abik == 0 { + continue + } + bi[k] = abik + if noUnit { + bi[k] *= a[k*lda+k] + } + c64.AxpyUnitary(abik, a[k*lda+k+1:k*lda+n], bi[k+1:]) + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for k := 0; k < n; k++ { + abik := alpha * bi[k] + if abik == 0 { + continue + } + bi[k] = abik + if noUnit { + bi[k] *= a[k*lda+k] + } + c64.AxpyUnitary(abik, a[k*lda:k*lda+k], bi[:k]) + } + } + } + } else { + // Form B = alpha*B*A^T or B = alpha*B*A^H. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j, bij := range bi { + if noConj { + if noUnit { + bij *= a[j*lda+j] + } + bij += c64.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + } else { + if noUnit { + bij *= cmplx.Conj(a[j*lda+j]) + } + bij += c64.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + } + bi[j] = alpha * bij + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + bij := bi[j] + if noConj { + if noUnit { + bij *= a[j*lda+j] + } + bij += c64.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) + } else { + if noUnit { + bij *= cmplx.Conj(a[j*lda+j]) + } + bij += c64.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) + } + bi[j] = alpha * bij + } + } + } + } + } +} + +// Ctrsm solves one of the matrix equations +// op(A) * X = alpha * B if side == blas.Left, +// X * op(A) = alpha * B if side == blas.Right, +// where alpha is a scalar, X and B are m×n matrices, A is a unit or +// non-unit, upper or lower triangular matrix and op(A) is one of +// op(A) = A if transA == blas.NoTrans, +// op(A) = A^T if transA == blas.Trans, +// op(A) = A^H if transA == blas.ConjTrans. +// On return the matrix X is overwritten on B. +// +// Complex64 implementations are autogenerated and not directly tested. +func (Implementation) Ctrsm(side blas.Side, uplo blas.Uplo, transA blas.Transpose, diag blas.Diag, m, n int, alpha complex64, a []complex64, lda int, b []complex64, ldb int) { + na := m + if side == blas.Right { + na = n + } + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case uplo != blas.Lower && uplo != blas.Upper: + panic(badUplo) + case transA != blas.NoTrans && transA != blas.Trans && transA != blas.ConjTrans: + panic(badTranspose) + case diag != blas.Unit && diag != blas.NonUnit: + panic(badDiag) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, na): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < (na-1)*lda+na { + panic(shortA) + } + if len(b) < (m-1)*ldb+n { + panic(shortB) + } + + if alpha == 0 { + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + b[i*ldb+j] = 0 + } + } + return + } + + noConj := transA != blas.ConjTrans + noUnit := diag == blas.NonUnit + if side == blas.Left { + if transA == blas.NoTrans { + // Form B = alpha*inv(A)*B. + if uplo == blas.Upper { + for i := m - 1; i >= 0; i-- { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c64.ScalUnitary(alpha, bi) + } + for ka, aik := range a[i*lda+i+1 : i*lda+m] { + k := i + 1 + ka + if aik != 0 { + c64.AxpyUnitary(-aik, b[k*ldb:k*ldb+n], bi) + } + } + if noUnit { + c64.ScalUnitary(1/a[i*lda+i], bi) + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c64.ScalUnitary(alpha, bi) + } + for j, aij := range a[i*lda : i*lda+i] { + if aij != 0 { + c64.AxpyUnitary(-aij, b[j*ldb:j*ldb+n], bi) + } + } + if noUnit { + c64.ScalUnitary(1/a[i*lda+i], bi) + } + } + } + } else { + // Form B = alpha*inv(A^T)*B or B = alpha*inv(A^H)*B. + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if noUnit { + if noConj { + c64.ScalUnitary(1/a[i*lda+i], bi) + } else { + c64.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) + } + } + for ja, aij := range a[i*lda+i+1 : i*lda+m] { + if aij == 0 { + continue + } + j := i + 1 + ja + if noConj { + c64.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) + } else { + c64.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) + } + } + if alpha != 1 { + c64.ScalUnitary(alpha, bi) + } + } + } else { + for i := m - 1; i >= 0; i-- { + bi := b[i*ldb : i*ldb+n] + if noUnit { + if noConj { + c64.ScalUnitary(1/a[i*lda+i], bi) + } else { + c64.ScalUnitary(1/cmplx.Conj(a[i*lda+i]), bi) + } + } + for j, aij := range a[i*lda : i*lda+i] { + if aij == 0 { + continue + } + if noConj { + c64.AxpyUnitary(-aij, bi, b[j*ldb:j*ldb+n]) + } else { + c64.AxpyUnitary(-cmplx.Conj(aij), bi, b[j*ldb:j*ldb+n]) + } + } + if alpha != 1 { + c64.ScalUnitary(alpha, bi) + } + } + } + } + } else { + if transA == blas.NoTrans { + // Form B = alpha*B*inv(A). + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c64.ScalUnitary(alpha, bi) + } + for j, bij := range bi { + if bij == 0 { + continue + } + if noUnit { + bi[j] /= a[j*lda+j] + } + c64.AxpyUnitary(-bi[j], a[j*lda+j+1:j*lda+n], bi[j+1:n]) + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + if alpha != 1 { + c64.ScalUnitary(alpha, bi) + } + for j := n - 1; j >= 0; j-- { + if bi[j] == 0 { + continue + } + if noUnit { + bi[j] /= a[j*lda+j] + } + c64.AxpyUnitary(-bi[j], a[j*lda:j*lda+j], bi[:j]) + } + } + } + } else { + // Form B = alpha*B*inv(A^T) or B = alpha*B*inv(A^H). + if uplo == blas.Upper { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j := n - 1; j >= 0; j-- { + bij := alpha * bi[j] + if noConj { + bij -= c64.DotuUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + if noUnit { + bij /= a[j*lda+j] + } + } else { + bij -= c64.DotcUnitary(a[j*lda+j+1:j*lda+n], bi[j+1:n]) + if noUnit { + bij /= cmplx.Conj(a[j*lda+j]) + } + } + bi[j] = bij + } + } + } else { + for i := 0; i < m; i++ { + bi := b[i*ldb : i*ldb+n] + for j, bij := range bi { + bij *= alpha + if noConj { + bij -= c64.DotuUnitary(a[j*lda:j*lda+j], bi[:j]) + if noUnit { + bij /= a[j*lda+j] + } + } else { + bij -= c64.DotcUnitary(a[j*lda:j*lda+j], bi[:j]) + if noUnit { + bij /= cmplx.Conj(a[j*lda+j]) + } + } + bi[j] = bij + } + } + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3single.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go similarity index 78% rename from vendor/gonum.org/v1/gonum/blas/gonum/level3single.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go index d24ce78c81a..13c4a792e98 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level3single.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3float32.go @@ -46,26 +46,30 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas if n < 0 { panic(nLT0) } - if ldb < n { - panic(badLdB) - } - var k int + k := n if s == blas.Left { k = m - } else { - k = n } - if lda*(k-1)+k > len(a) || lda < max(1, k) { + if lda < max(1, k) { panic(badLdA) } - if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + if ldb < max(1, n) { panic(badLdB) } + // Quick return if possible. if m == 0 || n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(k-1)+k { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if alpha == 0 { for i := 0; i < m; i++ { btmp := b[i*ldb : i*ldb+n] @@ -82,21 +86,17 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas for i := m - 1; i >= 0; i-- { btmp := b[i*ldb : i*ldb+n] if alpha != 1 { - for j := range btmp { - btmp[j] *= alpha - } + f32.ScalUnitary(alpha, btmp) } 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) + k := ka + i + 1 + f32.AxpyUnitary(-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 - } + f32.ScalUnitary(tmp, btmp) } } return @@ -104,20 +104,16 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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 - } + f32.ScalUnitary(alpha, btmp) } for k, va := range a[i*lda : i*lda+i] { if va != 0 { - f32.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + f32.AxpyUnitary(-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 - } + f32.ScalUnitary(tmp, btmp) } } return @@ -128,21 +124,16 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas btmpk := b[k*ldb : k*ldb+n] if nonUnit { tmp := 1 / a[k*lda+k] - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f32.ScalUnitary(tmp, btmpk) } 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) + i := ia + k + 1 + f32.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) } } if alpha != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= alpha - } + f32.ScalUnitary(alpha, btmpk) } } return @@ -151,20 +142,15 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas btmpk := b[k*ldb : k*ldb+n] if nonUnit { tmp := 1 / a[k*lda+k] - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f32.ScalUnitary(tmp, btmpk) } 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) + f32.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) } } if alpha != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= alpha - } + f32.ScalUnitary(alpha, btmpk) } } return @@ -175,38 +161,33 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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 - } + f32.ScalUnitary(alpha, btmp) } 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) - } + if vb == 0 { + continue } + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f32.AxpyUnitary(-btmp[k], a[k*lda+k+1:k*lda+n], btmp[k+1:n]) } } return } for i := 0; i < m; i++ { - btmp := b[i*lda : i*lda+n] + btmp := b[i*ldb : i*ldb+n] if alpha != 1 { - for j := 0; j < n; j++ { - btmp[j] *= alpha - } + f32.ScalUnitary(alpha, btmp) } 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) + if btmp[k] == 0 { + continue } + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f32.AxpyUnitary(-btmp[k], a[k*lda:k*lda+k], btmp[:k]) } } return @@ -214,7 +195,7 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas // Cases where a is transposed. if ul == blas.Upper { for i := 0; i < m; i++ { - btmp := b[i*lda : i*lda+n] + btmp := b[i*ldb : i*ldb+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 { @@ -226,9 +207,9 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas return } for i := 0; i < m; i++ { - btmp := b[i*lda : i*lda+n] + btmp := b[i*ldb : i*ldb+n] for j := 0; j < n; j++ { - tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda:j*lda+j], btmp) + tmp := alpha*btmp[j] - f32.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) if nonUnit { tmp /= a[j*lda+j] } @@ -246,7 +227,7 @@ func (Implementation) Strsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas // 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") + panic(badSide) } if ul != blas.Lower && ul != blas.Upper { panic(badUplo) @@ -257,27 +238,41 @@ func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, if n < 0 { panic(nLT0) } - var k int + k := n if s == blas.Left { k = m - } else { - k = n } - if lda*(k-1)+k > len(a) || lda < max(1, k) { + if lda < max(1, k) { panic(badLdA) } - if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + if ldb < max(1, n) { panic(badLdB) } - if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + if ldc < max(1, n) { panic(badLdC) } + + // Quick return if possible. if m == 0 || n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(k-1)+k { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if len(c) < ldc*(m-1)+n { + panic(shortC) + } + + // Quick return if possible. if alpha == 0 && beta == 1 { return } + if alpha == 0 { if beta == 0 { for i := 0; i < m; i++ { @@ -316,8 +311,7 @@ func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, 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) + f32.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) } for k := i + 1; k < m; k++ { var atmp float32 @@ -327,8 +321,7 @@ func (Implementation) Ssymm(s blas.Side, ul blas.Uplo, m, n int, alpha float32, 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) + f32.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) } } return @@ -388,21 +381,30 @@ func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo if k < 0 { panic(kLT0) } - if ldc < n { - panic(badLdC) - } - var row, col int + row, col := k, n if tA == blas.NoTrans { row, col = n, k - } else { - row, col = k, n } - if lda*(row-1)+col > len(a) || lda < max(1, col) { + if lda < max(1, col) { panic(badLdA) } - if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + if ldc < max(1, n) { panic(badLdC) } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(row-1)+col { + panic(shortA) + } + if len(c) < ldc*(n-1)+n { + panic(shortC) + } + if alpha == 0 { if beta == 0 { if ul == blas.Upper { @@ -444,17 +446,31 @@ func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo 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]) + if beta == 0 { + for jc := range ctmp { + j := jc + i + ctmp[jc] = alpha * f32.DotUnitary(atmp, a[j*lda:j*lda+k]) + } + } else { + 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++ { + ctmp := c[i*ldc : i*ldc+i+1] 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) + if beta == 0 { + for j := range ctmp { + ctmp[j] = alpha * f32.DotUnitary(a[j*lda:j*lda+k], atmp) + } + } else { + for j, vc := range ctmp { + ctmp[j] = vc*beta + alpha*f32.DotUnitary(a[j*lda:j*lda+k], atmp) + } } } return @@ -463,7 +479,11 @@ func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo if ul == blas.Upper { for i := 0; i < n; i++ { ctmp := c[i*ldc+i : i*ldc+n] - if beta != 1 { + if beta == 0 { + for j := range ctmp { + ctmp[j] = 0 + } + } else if beta != 1 { for j := range ctmp { ctmp[j] *= beta } @@ -471,7 +491,7 @@ func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo 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) + f32.AxpyUnitary(tmp, a[l*lda+i:l*lda+n], ctmp) } } } @@ -479,7 +499,7 @@ func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo } for i := 0; i < n; i++ { ctmp := c[i*ldc : i*ldc+i+1] - if beta != 0 { + if beta != 1 { for j := range ctmp { ctmp[j] *= beta } @@ -487,7 +507,7 @@ func (Implementation) Ssyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo 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) + f32.AxpyUnitary(tmp, a[l*lda:l*lda+i+1], ctmp) } } } @@ -513,24 +533,36 @@ func (Implementation) Ssyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha fl if k < 0 { panic(kLT0) } - if ldc < n { - panic(badLdC) - } - var row, col int + row, col := k, n if tA == blas.NoTrans { row, col = n, k - } else { - row, col = k, n } - if lda*(row-1)+col > len(a) || lda < max(1, col) { + if lda < max(1, col) { panic(badLdA) } - if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + if ldb < max(1, col) { panic(badLdB) } - if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + if ldc < max(1, n) { panic(badLdC) } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(row-1)+col { + panic(shortA) + } + if len(b) < ldb*(row-1)+col { + panic(shortB) + } + if len(c) < ldc*(n-1)+n { + panic(shortC) + } + if alpha == 0 { if beta == 0 { if ul == blas.Upper { @@ -613,7 +645,7 @@ func (Implementation) Ssyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha fl } } for l := 0; l < k; l++ { - tmp1 := alpha * b[l*lda+i] + tmp1 := alpha * b[l*ldb+i] tmp2 := alpha * a[l*lda+i] btmp := b[l*ldb+i : l*ldb+n] if tmp1 != 0 || tmp2 != 0 { @@ -633,7 +665,7 @@ func (Implementation) Ssyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha fl } } for l := 0; l < k; l++ { - tmp1 := alpha * b[l*lda+i] + tmp1 := alpha * b[l*ldb+i] tmp2 := alpha * a[l*lda+i] btmp := b[l*ldb : l*ldb+i+1] if tmp1 != 0 || tmp2 != 0 { @@ -672,18 +704,30 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas if n < 0 { panic(nLT0) } - var k int + k := n if s == blas.Left { k = m - } else { - k = n } - if lda*(k-1)+k > len(a) || lda < max(1, k) { + if lda < max(1, k) { panic(badLdA) } - if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + if ldb < max(1, n) { panic(badLdB) } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(k-1)+k { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if alpha == 0 { for i := 0; i < m; i++ { btmp := b[i*ldb : i*ldb+n] @@ -704,14 +748,11 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[i*lda+i] } btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] *= tmp - } + f32.ScalUnitary(tmp, btmp) 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) + if va != 0 { + f32.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) } } } @@ -723,13 +764,10 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[i*lda+i] } btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] *= tmp - } + f32.ScalUnitary(tmp, btmp) 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) + if va != 0 { + f32.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) } } } @@ -742,9 +780,8 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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) + if va != 0 { + f32.AxpyUnitary(alpha*va, btmpk, btmp) } } tmp := alpha @@ -752,9 +789,7 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[k*lda+k] } if tmp != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f32.ScalUnitary(tmp, btmpk) } } return @@ -763,9 +798,8 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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) + if va != 0 { + f32.AxpyUnitary(alpha*va, btmpk, btmp) } } tmp := alpha @@ -773,9 +807,7 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[k*lda+k] } if tmp != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f32.ScalUnitary(tmp, btmpk) } } return @@ -787,16 +819,14 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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 - } + if tmp == 0 { + continue } + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f32.AxpyUnitary(tmp, a[k*lda+k+1:k*lda+n], btmp[k+1:n]) } } return @@ -805,13 +835,14 @@ func (Implementation) Strmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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) + if tmp == 0 { + continue } + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f32.AxpyUnitary(tmp, a[k*lda:k*lda+k], btmp[:k]) } } return diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/level3double.go b/vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go similarity index 77% rename from vendor/gonum.org/v1/gonum/blas/gonum/level3double.go rename to vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go index 39e754d0a95..9eebd906912 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/level3double.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/level3float64.go @@ -42,26 +42,30 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas if n < 0 { panic(nLT0) } - if ldb < n { - panic(badLdB) - } - var k int + k := n if s == blas.Left { k = m - } else { - k = n } - if lda*(k-1)+k > len(a) || lda < max(1, k) { + if lda < max(1, k) { panic(badLdA) } - if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + if ldb < max(1, n) { panic(badLdB) } + // Quick return if possible. if m == 0 || n == 0 { return } + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(k-1)+k { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if alpha == 0 { for i := 0; i < m; i++ { btmp := b[i*ldb : i*ldb+n] @@ -78,21 +82,17 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas for i := m - 1; i >= 0; i-- { btmp := b[i*ldb : i*ldb+n] if alpha != 1 { - for j := range btmp { - btmp[j] *= alpha - } + f64.ScalUnitary(alpha, btmp) } 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) + k := ka + i + 1 + f64.AxpyUnitary(-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 - } + f64.ScalUnitary(tmp, btmp) } } return @@ -100,20 +100,16 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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 - } + f64.ScalUnitary(alpha, btmp) } for k, va := range a[i*lda : i*lda+i] { if va != 0 { - f64.AxpyUnitaryTo(btmp, -va, b[k*ldb:k*ldb+n], btmp) + f64.AxpyUnitary(-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 - } + f64.ScalUnitary(tmp, btmp) } } return @@ -124,21 +120,16 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas btmpk := b[k*ldb : k*ldb+n] if nonUnit { tmp := 1 / a[k*lda+k] - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f64.ScalUnitary(tmp, btmpk) } 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) + i := ia + k + 1 + f64.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) } } if alpha != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= alpha - } + f64.ScalUnitary(alpha, btmpk) } } return @@ -147,20 +138,15 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas btmpk := b[k*ldb : k*ldb+n] if nonUnit { tmp := 1 / a[k*lda+k] - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f64.ScalUnitary(tmp, btmpk) } 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) + f64.AxpyUnitary(-va, btmpk, b[i*ldb:i*ldb+n]) } } if alpha != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= alpha - } + f64.ScalUnitary(alpha, btmpk) } } return @@ -171,38 +157,33 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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 - } + f64.ScalUnitary(alpha, btmp) } 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) - } + if vb == 0 { + continue } + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f64.AxpyUnitary(-btmp[k], a[k*lda+k+1:k*lda+n], btmp[k+1:n]) } } return } for i := 0; i < m; i++ { - btmp := b[i*lda : i*lda+n] + btmp := b[i*ldb : i*ldb+n] if alpha != 1 { - for j := 0; j < n; j++ { - btmp[j] *= alpha - } + f64.ScalUnitary(alpha, btmp) } 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) + if btmp[k] == 0 { + continue } + if nonUnit { + btmp[k] /= a[k*lda+k] + } + f64.AxpyUnitary(-btmp[k], a[k*lda:k*lda+k], btmp[:k]) } } return @@ -210,7 +191,7 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas // Cases where a is transposed. if ul == blas.Upper { for i := 0; i < m; i++ { - btmp := b[i*lda : i*lda+n] + btmp := b[i*ldb : i*ldb+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 { @@ -222,9 +203,9 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas return } for i := 0; i < m; i++ { - btmp := b[i*lda : i*lda+n] + btmp := b[i*ldb : i*ldb+n] for j := 0; j < n; j++ { - tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda:j*lda+j], btmp) + tmp := alpha*btmp[j] - f64.DotUnitary(a[j*lda:j*lda+j], btmp[:j]) if nonUnit { tmp /= a[j*lda+j] } @@ -240,7 +221,7 @@ func (Implementation) Dtrsm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas // 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") + panic(badSide) } if ul != blas.Lower && ul != blas.Upper { panic(badUplo) @@ -251,27 +232,41 @@ func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, if n < 0 { panic(nLT0) } - var k int + k := n if s == blas.Left { k = m - } else { - k = n } - if lda*(k-1)+k > len(a) || lda < max(1, k) { + if lda < max(1, k) { panic(badLdA) } - if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + if ldb < max(1, n) { panic(badLdB) } - if ldc*(m-1)+n > len(c) || ldc < max(1, n) { + if ldc < max(1, n) { panic(badLdC) } + + // Quick return if possible. if m == 0 || n == 0 { return } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(k-1)+k { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if len(c) < ldc*(m-1)+n { + panic(shortC) + } + + // Quick return if possible. if alpha == 0 && beta == 1 { return } + if alpha == 0 { if beta == 0 { for i := 0; i < m; i++ { @@ -310,8 +305,7 @@ func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, 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) + f64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) } for k := i + 1; k < m; k++ { var atmp float64 @@ -321,8 +315,7 @@ func (Implementation) Dsymm(s blas.Side, ul blas.Uplo, m, n int, alpha float64, 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) + f64.AxpyUnitary(atmp, b[k*ldb:k*ldb+n], ctmp) } } return @@ -380,21 +373,30 @@ func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo if k < 0 { panic(kLT0) } - if ldc < n { - panic(badLdC) - } - var row, col int + row, col := k, n if tA == blas.NoTrans { row, col = n, k - } else { - row, col = k, n } - if lda*(row-1)+col > len(a) || lda < max(1, col) { + if lda < max(1, col) { panic(badLdA) } - if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + if ldc < max(1, n) { panic(badLdC) } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(row-1)+col { + panic(shortA) + } + if len(c) < ldc*(n-1)+n { + panic(shortC) + } + if alpha == 0 { if beta == 0 { if ul == blas.Upper { @@ -436,17 +438,31 @@ func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo 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]) + if beta == 0 { + for jc := range ctmp { + j := jc + i + ctmp[jc] = alpha * f64.DotUnitary(atmp, a[j*lda:j*lda+k]) + } + } else { + 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++ { + ctmp := c[i*ldc : i*ldc+i+1] 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) + if beta == 0 { + for j := range ctmp { + ctmp[j] = alpha * f64.DotUnitary(a[j*lda:j*lda+k], atmp) + } + } else { + for j, vc := range ctmp { + ctmp[j] = vc*beta + alpha*f64.DotUnitary(a[j*lda:j*lda+k], atmp) + } } } return @@ -455,7 +471,11 @@ func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo if ul == blas.Upper { for i := 0; i < n; i++ { ctmp := c[i*ldc+i : i*ldc+n] - if beta != 1 { + if beta == 0 { + for j := range ctmp { + ctmp[j] = 0 + } + } else if beta != 1 { for j := range ctmp { ctmp[j] *= beta } @@ -463,7 +483,7 @@ func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo 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) + f64.AxpyUnitary(tmp, a[l*lda+i:l*lda+n], ctmp) } } } @@ -471,7 +491,7 @@ func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo } for i := 0; i < n; i++ { ctmp := c[i*ldc : i*ldc+i+1] - if beta != 0 { + if beta != 1 { for j := range ctmp { ctmp[j] *= beta } @@ -479,7 +499,7 @@ func (Implementation) Dsyrk(ul blas.Uplo, tA blas.Transpose, n, k int, alpha flo 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) + f64.AxpyUnitary(tmp, a[l*lda:l*lda+i+1], ctmp) } } } @@ -503,24 +523,36 @@ func (Implementation) Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha fl if k < 0 { panic(kLT0) } - if ldc < n { - panic(badLdC) - } - var row, col int + row, col := k, n if tA == blas.NoTrans { row, col = n, k - } else { - row, col = k, n } - if lda*(row-1)+col > len(a) || lda < max(1, col) { + if lda < max(1, col) { panic(badLdA) } - if ldb*(row-1)+col > len(b) || ldb < max(1, col) { + if ldb < max(1, col) { panic(badLdB) } - if ldc*(n-1)+n > len(c) || ldc < max(1, n) { + if ldc < max(1, n) { panic(badLdC) } + + // Quick return if possible. + if n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(row-1)+col { + panic(shortA) + } + if len(b) < ldb*(row-1)+col { + panic(shortB) + } + if len(c) < ldc*(n-1)+n { + panic(shortC) + } + if alpha == 0 { if beta == 0 { if ul == blas.Upper { @@ -603,7 +635,7 @@ func (Implementation) Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha fl } } for l := 0; l < k; l++ { - tmp1 := alpha * b[l*lda+i] + tmp1 := alpha * b[l*ldb+i] tmp2 := alpha * a[l*lda+i] btmp := b[l*ldb+i : l*ldb+n] if tmp1 != 0 || tmp2 != 0 { @@ -623,7 +655,7 @@ func (Implementation) Dsyr2k(ul blas.Uplo, tA blas.Transpose, n, k int, alpha fl } } for l := 0; l < k; l++ { - tmp1 := alpha * b[l*lda+i] + tmp1 := alpha * b[l*ldb+i] tmp2 := alpha * a[l*lda+i] btmp := b[l*ldb : l*ldb+i+1] if tmp1 != 0 || tmp2 != 0 { @@ -660,18 +692,30 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas if n < 0 { panic(nLT0) } - var k int + k := n if s == blas.Left { k = m - } else { - k = n } - if lda*(k-1)+k > len(a) || lda < max(1, k) { + if lda < max(1, k) { panic(badLdA) } - if ldb*(m-1)+n > len(b) || ldb < max(1, n) { + if ldb < max(1, n) { panic(badLdB) } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if len(a) < lda*(k-1)+k { + panic(shortA) + } + if len(b) < ldb*(m-1)+n { + panic(shortB) + } + if alpha == 0 { for i := 0; i < m; i++ { btmp := b[i*ldb : i*ldb+n] @@ -692,14 +736,11 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[i*lda+i] } btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] *= tmp - } + f64.ScalUnitary(tmp, btmp) 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) + if va != 0 { + f64.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) } } } @@ -711,13 +752,10 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[i*lda+i] } btmp := b[i*ldb : i*ldb+n] - for j := range btmp { - btmp[j] *= tmp - } + f64.ScalUnitary(tmp, btmp) 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) + if va != 0 { + f64.AxpyUnitary(alpha*va, b[k*ldb:k*ldb+n], btmp) } } } @@ -730,9 +768,8 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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) + if va != 0 { + f64.AxpyUnitary(alpha*va, btmpk, btmp) } } tmp := alpha @@ -740,9 +777,7 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[k*lda+k] } if tmp != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f64.ScalUnitary(tmp, btmpk) } } return @@ -751,9 +786,8 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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) + if va != 0 { + f64.AxpyUnitary(alpha*va, btmpk, btmp) } } tmp := alpha @@ -761,9 +795,7 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas tmp *= a[k*lda+k] } if tmp != 1 { - for j := 0; j < n; j++ { - btmpk[j] *= tmp - } + f64.ScalUnitary(tmp, btmpk) } } return @@ -775,16 +807,14 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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 - } + if tmp == 0 { + continue } + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f64.AxpyUnitary(tmp, a[k*lda+k+1:k*lda+n], btmp[k+1:n]) } } return @@ -793,13 +823,14 @@ func (Implementation) Dtrmm(s blas.Side, ul blas.Uplo, tA blas.Transpose, d blas 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) + if tmp == 0 { + continue } + btmp[k] = tmp + if nonUnit { + btmp[k] *= a[k*lda+k] + } + f64.AxpyUnitary(tmp, a[k*lda:k*lda+k], btmp[:k]) } } return diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go b/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go index 24a8b7ed950..e868a1050cf 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go +++ b/vendor/gonum.org/v1/gonum/blas/gonum/sgemm.go @@ -25,25 +25,81 @@ import ( // // 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 { + switch tA { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: } - if tB != blas.NoTrans && tB != blas.Trans && tB != blas.ConjTrans { + switch tB { + default: panic(badTranspose) + case blas.NoTrans, blas.Trans, blas.ConjTrans: + } + if m < 0 { + panic(mLT0) + } + if n < 0 { + panic(nLT0) + } + if k < 0 { + panic(kLT0) } aTrans := tA == blas.Trans || tA == blas.ConjTrans if aTrans { - checkSMatrix('a', k, m, a, lda) + if lda < max(1, m) { + panic(badLdA) + } } else { - checkSMatrix('a', m, k, a, lda) + if lda < max(1, k) { + panic(badLdA) + } } bTrans := tB == blas.Trans || tB == blas.ConjTrans if bTrans { - checkSMatrix('b', n, k, b, ldb) + if ldb < max(1, k) { + panic(badLdB) + } } else { - checkSMatrix('b', k, n, b, ldb) + if ldb < max(1, n) { + panic(badLdB) + } + } + if ldc < max(1, n) { + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + // For zero matrix size the following slice length checks are trivially satisfied. + if aTrans { + if len(a) < (k-1)*lda+m { + panic(shortA) + } + } else { + if len(a) < (m-1)*lda+k { + panic(shortA) + } + } + if bTrans { + if len(b) < (n-1)*ldb+k { + panic(shortB) + } + } else { + if len(b) < (k-1)*ldb+n { + panic(shortB) + } + } + if len(c) < (m-1)*ldc+n { + panic(shortC) + } + + // Quick return if possible. + if (alpha == 0 || k == 0) && beta == 1 { + return } - checkSMatrix('c', m, n, c, ldc) // scale c if beta != 1 { @@ -128,13 +184,6 @@ func sgemmParallel(aTrans, bTrans bool, m, n, k int, a []float32, lda int, b []f wg.Add(1) go func() { defer wg.Done() - // Make local copies of otherwise global variables to reduce shared memory. - // This has a noticeable 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 @@ -214,7 +263,7 @@ func sgemmSerialNotNot(m, n, k int, a []float32, lda int, b []float32, ldb int, 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) + f32.AxpyUnitary(tmp, b[l*ldb:l*ldb+n], ctmp) } } } @@ -230,7 +279,7 @@ func sgemmSerialTransNot(m, n, k int, a []float32, lda int, b []float32, ldb int tmp := alpha * v if tmp != 0 { ctmp := c[i*ldc : i*ldc+n] - f32.AxpyUnitaryTo(ctmp, tmp, btmp, ctmp) + f32.AxpyUnitary(tmp, btmp, ctmp) } } } diff --git a/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash b/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash index 00d1b8822c3..53db63a7f0f 100644 --- a/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash +++ b/vendor/gonum.org/v1/gonum/blas/gonum/single_precision.bash @@ -4,126 +4,180 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -WARNING='//\ +WARNINGF32='//\ // Float32 implementations are autogenerated and not directly tested.\ ' +WARNINGC64='//\ +// Complex64 implementations are autogenerated and not directly tested.\ +' # Level1 routines. -echo Generating level1single.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single.go -cat level1double.go \ +echo Generating level1float32.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32.go +cat level1float64.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.AxpyUnitary -> f32.AxpyUnitary' \ -| gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ | gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ | gofmt -r 'f64.ScalInc -> f32.ScalInc' \ | gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ \ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ -e 's_^// D_// S_' \ - -e "s_^\(func (Implementation) \)Id\(.*\)\$_$WARNING\1Is\2_" \ + -e "s_^\(func (Implementation) \)Id\(.*\)\$_$WARNINGF32\1Is\2_" \ -e 's_^// Id_// Is_' \ -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ ->> level1single.go +>> level1float32.go -echo Generating level1single_sdot.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single_sdot.go -cat level1double_ddot.go \ +echo Generating level1cmplx64.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1cmplx64.go +cat level1cmplx128.go \ +| gofmt -r 'blas.Complex128Level1 -> blas.Complex64Level1' \ +\ +| gofmt -r 'float64 -> float32' \ +| gofmt -r 'complex128 -> complex64' \ +\ +| gofmt -r 'c128.AxpyInc -> c64.AxpyInc' \ +| gofmt -r 'c128.AxpyUnitary -> c64.AxpyUnitary' \ +| gofmt -r 'c128.DotcInc -> c64.DotcInc' \ +| gofmt -r 'c128.DotcUnitary -> c64.DotcUnitary' \ +| gofmt -r 'c128.DotuInc -> c64.DotuInc' \ +| gofmt -r 'c128.DotuUnitary -> c64.DotuUnitary' \ +| gofmt -r 'c128.ScalInc -> c64.ScalInc' \ +| gofmt -r 'c128.ScalUnitary -> c64.ScalUnitary' \ +| gofmt -r 'dcabs1 -> scabs1' \ +\ +| sed -e "s_^\(func (Implementation) \)Zdot\(.*\)\$_$WARNINGC64\1Cdot\2_" \ + -e 's_^// Zdot_// Cdot_' \ + -e "s_^\(func (Implementation) \)Zdscal\(.*\)\$_$WARNINGC64\1Csscal\2_" \ + -e 's_^// Zdscal_// Csscal_' \ + -e "s_^\(func (Implementation) \)Z\(.*\)\$_$WARNINGC64\1C\2_" \ + -e 's_^// Z_// C_' \ + -e "s_^\(func (Implementation) \)Iz\(.*\)\$_$WARNINGC64\1Ic\2_" \ + -e 's_^// Iz_// Ic_' \ + -e "s_^\(func (Implementation) \)Dz\(.*\)\$_$WARNINGC64\1Sc\2_" \ + -e 's_^// Dz_// Sc_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/c128"_"gonum.org/v1/gonum/internal/asm/c64"_' \ + -e 's_"math"_math "gonum.org/v1/gonum/internal/math32"_' \ +>> level1cmplx64.go + +echo Generating level1float32_sdot.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32_sdot.go +cat level1float64_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_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ -e 's_^// D_// S_' \ -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level1single_sdot.go +>> level1float32_sdot.go -echo Generating level1single_dsdot.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single_dsdot.go -cat level1double_ddot.go \ +echo Generating level1float32_dsdot.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32_dsdot.go +cat level1float64_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_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1Ds\2_" \ -e 's_^// D_// Ds_' \ -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level1single_dsdot.go +>> level1float32_dsdot.go -echo Generating level1single_sdsdot.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1single_sdsdot.go -cat level1double_ddot.go \ +echo Generating level1float32_sdsdot.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level1float32_sdsdot.go +cat level1float64_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_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\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_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level1single_sdsdot.go +>> level1float32_sdsdot.go # Level2 routines. -echo Generating level2single.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level2single.go -cat level2double.go \ +echo Generating level2float32.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level2float32.go +cat level2float64.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' \ +| gofmt -r 'f64.ScalInc -> f32.ScalInc' \ +| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ | gofmt -r 'f64.Ger -> f32.Ger' \ \ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ -e 's_^// D_// S_' \ -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level2single.go +>> level2float32.go +echo Generating level2cmplx64.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level2cmplx64.go +cat level2cmplx128.go \ +| gofmt -r 'blas.Complex128Level2 -> blas.Complex64Level2' \ +\ +| gofmt -r 'complex128 -> complex64' \ +| gofmt -r 'float64 -> float32' \ +\ +| gofmt -r 'c128.AxpyInc -> c64.AxpyInc' \ +| gofmt -r 'c128.AxpyUnitary -> c64.AxpyUnitary' \ +| gofmt -r 'c128.DotuInc -> c64.DotuInc' \ +| gofmt -r 'c128.DotuUnitary -> c64.DotuUnitary' \ +| gofmt -r 'c128.ScalInc -> c64.ScalInc' \ +| gofmt -r 'c128.ScalUnitary -> c64.ScalUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)Z\(.*\)\$_$WARNINGC64\1C\2_" \ + -e 's_^// Z_// C_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/c128"_"gonum.org/v1/gonum/internal/asm/c64"_' \ + -e 's_"math/cmplx"_cmplx "gonum.org/v1/gonum/internal/cmplx64"_' \ +>> level2cmplx64.go # Level3 routines. -echo Generating level3single.go -echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level3single.go -cat level3double.go \ +echo Generating level3float32.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level3float32.go +cat level3float64.go \ | gofmt -r 'blas.Float64Level3 -> blas.Float32Level3' \ \ | gofmt -r 'float64 -> float32' \ \ | gofmt -r 'f64.AxpyUnitaryTo -> f32.AxpyUnitaryTo' \ +| gofmt -r 'f64.AxpyUnitary -> f32.AxpyUnitary' \ | gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ +| gofmt -r 'f64.ScalUnitary -> f32.ScalUnitary' \ \ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ -e 's_^// D_// S_' \ -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ ->> level3single.go +>> level3float32.go echo Generating sgemm.go echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > sgemm.go cat dgemm.go \ | gofmt -r 'float64 -> float32' \ | gofmt -r 'sliceView64 -> sliceView32' \ -| gofmt -r 'checkDMatrix -> checkSMatrix' \ \ | gofmt -r 'dgemmParallel -> sgemmParallel' \ | gofmt -r 'computeNumBlocks64 -> computeNumBlocks32' \ @@ -134,12 +188,31 @@ cat dgemm.go \ | 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.AxpyUnitary -> f32.AxpyUnitary' \ | gofmt -r 'f64.DotUnitary -> f32.DotUnitary' \ \ -| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNING\1S\2_" \ +| sed -e "s_^\(func (Implementation) \)D\(.*\)\$_$WARNINGF32\1S\2_" \ -e 's_^// D_// S_' \ -e 's_^// d_// s_' \ -e 's_"gonum.org/v1/gonum/internal/asm/f64"_"gonum.org/v1/gonum/internal/asm/f32"_' \ >> sgemm.go + +echo Generating level3cmplx64.go +echo -e '// Code generated by "go generate gonum.org/v1/gonum/blas/gonum”; DO NOT EDIT.\n' > level3cmplx64.go +cat level3cmplx128.go \ +| gofmt -r 'blas.Complex128Level3 -> blas.Complex64Level3' \ +\ +| gofmt -r 'float64 -> float32' \ +| gofmt -r 'complex128 -> complex64' \ +\ +| gofmt -r 'c128.ScalUnitary -> c64.ScalUnitary' \ +| gofmt -r 'c128.DscalUnitary -> c64.SscalUnitary' \ +| gofmt -r 'c128.DotcUnitary -> c64.DotcUnitary' \ +| gofmt -r 'c128.AxpyUnitary -> c64.AxpyUnitary' \ +| gofmt -r 'c128.DotuUnitary -> c64.DotuUnitary' \ +\ +| sed -e "s_^\(func (Implementation) \)Z\(.*\)\$_$WARNINGC64\1C\2_" \ + -e 's_^// Z_// C_' \ + -e 's_"gonum.org/v1/gonum/internal/asm/c128"_"gonum.org/v1/gonum/internal/asm/c64"_' \ + -e 's_"math/cmplx"_cmplx "gonum.org/v1/gonum/internal/cmplx64"_' \ +>> level3cmplx64.go diff --git a/vendor/gonum.org/v1/gonum/floats/floats.go b/vendor/gonum.org/v1/gonum/floats/floats.go index 81d85e80120..ae004a6215b 100644 --- a/vendor/gonum.org/v1/gonum/floats/floats.go +++ b/vendor/gonum.org/v1/gonum/floats/floats.go @@ -1,4 +1,4 @@ -// Copyright 2013 The Gonum Authors. All rights reserved. +// 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 @@ -37,9 +37,7 @@ func AddTo(dst, s, t []float64) []float64 { // 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 - } + f64.AddConst(c, dst) } // AddScaled performs dst = dst + alpha * s. @@ -811,6 +809,17 @@ func Scale(c float64, dst []float64) { } } +// ScaleTo multiplies the elements in s by c and stores the result in dst. +func ScaleTo(dst []float64, c float64, s []float64) []float64 { + if len(dst) != len(s) { + panic("floats: lengths of slices do not match") + } + if len(dst) > 0 { + f64.ScalUnitaryTo(dst, c, s) + } + return 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. @@ -899,11 +908,7 @@ func SubTo(dst, s, t []float64) []float64 { // 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 + return f64.Sum(s) } // Within returns the first index i where s[i] <= v < s[i+1]. Within panics if: diff --git a/vendor/gonum.org/v1/gonum/graph/BUILD b/vendor/gonum.org/v1/gonum/graph/BUILD index 7049ca1b4eb..7ac8a1d0109 100644 --- a/vendor/gonum.org/v1/gonum/graph/BUILD +++ b/vendor/gonum.org/v1/gonum/graph/BUILD @@ -6,6 +6,7 @@ go_library( "doc.go", "graph.go", "multigraph.go", + "nodes_edges.go", "undirect.go", ], importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/graph", @@ -30,6 +31,7 @@ filegroup( "//vendor/gonum.org/v1/gonum/graph/internal/ordered:all-srcs", "//vendor/gonum.org/v1/gonum/graph/internal/set:all-srcs", "//vendor/gonum.org/v1/gonum/graph/internal/uid:all-srcs", + "//vendor/gonum.org/v1/gonum/graph/iterator:all-srcs", "//vendor/gonum.org/v1/gonum/graph/simple:all-srcs", "//vendor/gonum.org/v1/gonum/graph/topo:all-srcs", "//vendor/gonum.org/v1/gonum/graph/traverse:all-srcs", diff --git a/vendor/gonum.org/v1/gonum/graph/doc.go b/vendor/gonum.org/v1/gonum/graph/doc.go index 0e76ac22991..7eedd09ce80 100644 --- a/vendor/gonum.org/v1/gonum/graph/doc.go +++ b/vendor/gonum.org/v1/gonum/graph/doc.go @@ -3,4 +3,7 @@ // license that can be found in the LICENSE file. // Package graph defines graph interfaces. +// +// Routines to test contract compliance by user implemented graph types +// are available in gonum.org/v1/gonum/graph/testgraph. package graph // import "gonum.org/v1/gonum/graph" diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/BUILD b/vendor/gonum.org/v1/gonum/graph/encoding/dot/BUILD index c41daffb733..4f3b4e27e96 100644 --- a/vendor/gonum.org/v1/gonum/graph/encoding/dot/BUILD +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/BUILD @@ -5,7 +5,6 @@ go_library( srcs = [ "decode.go", "doc.go", - "dot.go", "encode.go", ], importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/graph/encoding/dot", diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go index c410b88880a..779da01ad8a 100644 --- a/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/decode.go @@ -6,6 +6,8 @@ package dot import ( "fmt" + "strconv" + "strings" "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/encoding" @@ -39,15 +41,38 @@ type PortSetter interface { } // Unmarshal parses the Graphviz DOT-encoded data and stores the result in dst. +// If the number of graphs encoded in data is not one, an error is returned and +// dst will hold the first graph in data. +// +// Attributes and IDs are unquoted during unmarshalling if appropriate. func Unmarshal(data []byte, dst encoding.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)) + err = copyGraph(dst, file.Graphs[0]) + if err == nil && len(file.Graphs) != 1 { + err = fmt.Errorf("invalid number of graphs; expected 1, got %d", len(file.Graphs)) } - return copyGraph(dst, file.Graphs[0]) + return err +} + +// UnmarshalMulti parses the Graphviz DOT-encoded data as a multigraph and +// stores the result in dst. +// If the number of graphs encoded in data is not one, an error is returned and +// dst will hold the first graph in data. +// +// Attributes and IDs are unquoted during unmarshalling if appropriate. +func UnmarshalMulti(data []byte, dst encoding.MultiBuilder) error { + file, err := dot.ParseBytes(data) + if err != nil { + return err + } + err = copyMultigraph(dst, file.Graphs[0]) + if err == nil && len(file.Graphs) != 1 { + err = fmt.Errorf("invalid number of graphs; expected 1, got %d", len(file.Graphs)) + } + return err } // copyGraph copies the nodes and edges from the Graphviz AST source graph to @@ -62,12 +87,44 @@ func copyGraph(dst encoding.Builder, src *ast.Graph) (err error) { panic(e) } }() - gen := &generator{ - directed: src.Directed, - ids: make(map[string]graph.Node), + gen := &simpleGraph{ + generator: generator{ + directed: src.Directed, + ids: make(map[string]graph.Node), + }, } if dst, ok := dst.(DOTIDSetter); ok { - dst.SetDOTID(src.ID) + dst.SetDOTID(unquoteID(src.ID)) + } + if a, ok := dst.(AttributeSetters); ok { + gen.graphAttr, gen.nodeAttr, gen.edgeAttr = a.DOTAttributeSetters() + } + for _, stmt := range src.Stmts { + gen.addStmt(dst, stmt) + } + return err +} + +// copyMultigraph copies the nodes and edges from the Graphviz AST source graph to +// the destination graph. Edge direction is maintained if present. +func copyMultigraph(dst encoding.MultiBuilder, src *ast.Graph) (err error) { + defer func() { + switch e := recover().(type) { + case nil: + case error: + err = e + default: + panic(e) + } + }() + gen := &multiGraph{ + generator: generator{ + directed: src.Directed, + ids: make(map[string]graph.Node), + }, + } + if dst, ok := dst.(DOTIDSetter); ok { + dst.SetDOTID(unquoteID(src.ID)) } if a, ok := dst.(AttributeSetters); ok { gen.graphAttr, gen.nodeAttr, gen.edgeAttr = a.DOTAttributeSetters() @@ -97,15 +154,15 @@ type generator struct { // 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 encoding.Builder, id string) graph.Node { +func (gen *generator) node(dst graph.NodeAdder, id string) graph.Node { if n, ok := gen.ids[id]; ok { return n } n := dst.NewNode() - dst.AddNode(n) if n, ok := n.(DOTIDSetter); ok { - n.SetDOTID(id) + n.SetDOTID(unquoteID(id)) } + dst.AddNode(n) gen.ids[id] = n // Check if within the context of a subgraph, that is to be used as a vertex // of an edge. @@ -117,8 +174,10 @@ func (gen *generator) node(dst encoding.Builder, id string) graph.Node { return n } +type simpleGraph struct{ generator } + // addStmt adds the given statement to the graph. -func (gen *generator) addStmt(dst encoding.Builder, stmt ast.Stmt) { +func (gen *simpleGraph) addStmt(dst encoding.Builder, stmt ast.Stmt) { switch stmt := stmt.(type) { case *ast.NodeStmt: n, ok := gen.node(dst, stmt.Node.ID).(encoding.AttributeSetter) @@ -127,11 +186,11 @@ func (gen *generator) addStmt(dst encoding.Builder, stmt ast.Stmt) { } for _, attr := range stmt.Attrs { a := encoding.Attribute{ - Key: attr.Key, - Value: attr.Val, + Key: unquoteID(attr.Key), + Value: unquoteID(attr.Val), } if err := n.SetAttribute(a); err != nil { - panic(fmt.Errorf("unable to unmarshal node DOT attribute (%s=%s)", a.Key, a.Value)) + panic(fmt.Errorf("unable to unmarshal node DOT attribute (%s=%s): %v", a.Key, a.Value, err)) } } case *ast.EdgeStmt: @@ -163,11 +222,11 @@ func (gen *generator) addStmt(dst encoding.Builder, stmt ast.Stmt) { } for _, attr := range stmt.Attrs { a := encoding.Attribute{ - Key: attr.Key, - Value: attr.Val, + Key: unquoteID(attr.Key), + Value: unquoteID(attr.Val), } if err := n.SetAttribute(a); err != nil { - panic(fmt.Errorf("unable to unmarshal global %s DOT attribute (%s=%s)", dst, a.Key, a.Value)) + panic(fmt.Errorf("unable to unmarshal global %s DOT attribute (%s=%s): %v", dst, a.Key, a.Value, err)) } } case *ast.Attr: @@ -181,13 +240,20 @@ func (gen *generator) addStmt(dst encoding.Builder, stmt ast.Stmt) { } } +// basicEdge is an edge without the Reverse method to +// allow satisfaction by both graph.Edge and graph.Line. +type basicEdge interface { + From() graph.Node + To() graph.Node +} + // applyPortsToEdge applies the available port metadata from an ast.Edge // to a graph.Edge -func applyPortsToEdge(from ast.Vertex, to *ast.Edge, edge graph.Edge) { +func applyPortsToEdge(from ast.Vertex, to *ast.Edge, edge basicEdge) { if ps, isPortSetter := edge.(PortSetter); isPortSetter { if n, vertexIsNode := from.(*ast.Node); vertexIsNode { if n.Port != nil { - err := ps.SetFromPort(n.Port.ID, n.Port.CompassPoint.String()) + err := ps.SetFromPort(unquoteID(n.Port.ID), n.Port.CompassPoint.String()) if err != nil { panic(fmt.Errorf("unable to unmarshal edge port (:%s:%s)", n.Port.ID, n.Port.CompassPoint.String())) } @@ -196,7 +262,7 @@ func applyPortsToEdge(from ast.Vertex, to *ast.Edge, edge graph.Edge) { if n, vertexIsNode := to.Vertex.(*ast.Node); vertexIsNode { if n.Port != nil { - err := ps.SetToPort(n.Port.ID, n.Port.CompassPoint.String()) + err := ps.SetToPort(unquoteID(n.Port.ID), n.Port.CompassPoint.String()) if err != nil { panic(fmt.Errorf("unable to unmarshal edge DOT port (:%s:%s)", n.Port.ID, n.Port.CompassPoint.String())) } @@ -206,7 +272,7 @@ func applyPortsToEdge(from ast.Vertex, to *ast.Edge, edge graph.Edge) { } // addEdgeStmt adds the given edge statement to the graph. -func (gen *generator) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) { +func (gen *simpleGraph) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) { fs := gen.addVertex(dst, stmt.From) ts := gen.addEdge(dst, stmt.To, stmt.Attrs) for _, f := range fs { @@ -220,7 +286,7 @@ func (gen *generator) addEdgeStmt(dst encoding.Builder, stmt *ast.EdgeStmt) { } // addVertex adds the given vertex to the graph, and returns its set of nodes. -func (gen *generator) addVertex(dst encoding.Builder, v ast.Vertex) []graph.Node { +func (gen *simpleGraph) addVertex(dst encoding.Builder, v ast.Vertex) []graph.Node { switch v := v.(type) { case *ast.Node: n := gen.node(dst, v.ID) @@ -237,7 +303,7 @@ func (gen *generator) addVertex(dst encoding.Builder, v ast.Vertex) []graph.Node } // addEdge adds the given edge to the graph, and returns its set of nodes. -func (gen *generator) addEdge(dst encoding.Builder, to *ast.Edge, attrs []*ast.Attr) []graph.Node { +func (gen *simpleGraph) addEdge(dst encoding.Builder, to *ast.Edge, attrs []*ast.Attr) []graph.Node { if !gen.directed && to.Directed { panic(fmt.Errorf("directed edge to %v in undirected graph", to.Vertex)) } @@ -307,19 +373,155 @@ func (gen *generator) appendSubgraphNode(n graph.Node) { gen.subNodes = append(gen.subNodes, n) } +type multiGraph struct{ generator } + +// addStmt adds the given statement to the multigraph. +func (gen *multiGraph) addStmt(dst encoding.MultiBuilder, stmt ast.Stmt) { + switch stmt := stmt.(type) { + case *ast.NodeStmt: + n, ok := gen.node(dst, stmt.Node.ID).(encoding.AttributeSetter) + if !ok { + return + } + for _, attr := range stmt.Attrs { + a := encoding.Attribute{ + Key: unquoteID(attr.Key), + Value: unquoteID(attr.Val), + } + if err := n.SetAttribute(a); err != nil { + panic(fmt.Errorf("unable to unmarshal node DOT attribute (%s=%s): %v", a.Key, a.Value, err)) + } + } + case *ast.EdgeStmt: + gen.addEdgeStmt(dst, stmt) + case *ast.AttrStmt: + var n encoding.AttributeSetter + var dst string + switch stmt.Kind { + case ast.GraphKind: + if gen.graphAttr == nil { + return + } + n = gen.graphAttr + dst = "graph" + case ast.NodeKind: + if gen.nodeAttr == nil { + return + } + n = gen.nodeAttr + dst = "node" + case ast.EdgeKind: + if gen.edgeAttr == nil { + return + } + n = gen.edgeAttr + dst = "edge" + default: + panic("unreachable") + } + for _, attr := range stmt.Attrs { + a := encoding.Attribute{ + Key: unquoteID(attr.Key), + Value: unquoteID(attr.Val), + } + if err := n.SetAttribute(a); err != nil { + panic(fmt.Errorf("unable to unmarshal global %s DOT attribute (%s=%s): %v", dst, a.Key, a.Value, err)) + } + } + 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 multigraph. +func (gen *multiGraph) addEdgeStmt(dst encoding.MultiBuilder, stmt *ast.EdgeStmt) { + fs := gen.addVertex(dst, stmt.From) + ts := gen.addLine(dst, stmt.To, stmt.Attrs) + for _, f := range fs { + for _, t := range ts { + edge := dst.NewLine(f, t) + dst.SetLine(edge) + applyPortsToEdge(stmt.From, stmt.To, edge) + addEdgeAttrs(edge, stmt.Attrs) + } + } +} + +// addVertex adds the given vertex to the multigraph, and returns its set of nodes. +func (gen *multiGraph) addVertex(dst encoding.MultiBuilder, 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)) + } +} + +// addLine adds the given edge to the multigraph, and returns its set of nodes. +func (gen *multiGraph) addLine(dst encoding.MultiBuilder, to *ast.Edge, attrs []*ast.Attr) []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.addLine(dst, to.To, attrs) + for _, f := range fs { + for _, t := range ts { + edge := dst.NewLine(f, t) + dst.SetLine(edge) + applyPortsToEdge(to.Vertex, to.To, edge) + addEdgeAttrs(edge, attrs) + } + } + } + return fs +} + // addEdgeAttrs adds the attributes to the given edge. -func addEdgeAttrs(edge graph.Edge, attrs []*ast.Attr) { +func addEdgeAttrs(edge basicEdge, attrs []*ast.Attr) { e, ok := edge.(encoding.AttributeSetter) if !ok { return } for _, attr := range attrs { a := encoding.Attribute{ - Key: attr.Key, - Value: attr.Val, + Key: unquoteID(attr.Key), + Value: unquoteID(attr.Val), } if err := e.SetAttribute(a); err != nil { - panic(fmt.Errorf("unable to unmarshal edge DOT attribute (%s=%s)", a.Key, a.Value)) + panic(fmt.Errorf("unable to unmarshal edge DOT attribute (%s=%s): %v", a.Key, a.Value, err)) } } } + +// unquoteID unquotes the given string if needed in the context of an ID. If s +// is not already quoted the original string is returned. +func unquoteID(s string) string { + // To make round-trips idempotent, don't unquote quoted HTML-like strings + // + // /^"<.*>"$/ + if len(s) >= 4 && strings.HasPrefix(s, `"<`) && strings.HasSuffix(s, `>"`) { + return s + } + // Unquote quoted string if possible. + if t, err := strconv.Unquote(s); err == nil { + return t + } + // On error, either s is not quoted or s is quoted but contains invalid + // characters, in both cases we return the original string rather than + // panicking. + return s +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go index 697bb7c1d51..235ac0f02ef 100644 --- a/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/doc.go @@ -7,8 +7,15 @@ // 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 Guide: https://www.graphviz.org/pdf/dotguide.pdf // // DOT grammar: http://www.graphviz.org/doc/info/lang.html // +// Attribute quoting +// +// Attributes and IDs are quoted if needed during marshalling, to conform with +// valid DOT syntax. Quoted IDs and attributes are unquoted during unmarshaling, +// so the data is kept in raw form. As an exception, quoted text with a leading +// `"<` and a trailing `>"` is not unquoted to ensure preservation of the string +// during a round-trip. package dot // import "gonum.org/v1/gonum/graph/encoding/dot" diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go b/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go index 4664c10f210..10fc7d956ea 100644 --- a/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go +++ b/vendor/gonum.org/v1/gonum/graph/encoding/dot/encode.go @@ -8,7 +8,9 @@ import ( "bytes" "errors" "fmt" + "regexp" "sort" + "strconv" "strings" "gonum.org/v1/gonum/graph" @@ -38,15 +40,15 @@ type Attributers interface { // 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 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 returns the port and compass for the - // From node of a graph.Edge. + // FromPort returns the port and compass for + // the From node of a graph.Edge. FromPort() (port, compass string) - // ToPort returns the port and compass for the - // To node of a graph.Edge. + // ToPort returns the port and compass for + // the To node of a graph.Edge. ToPort() (port, compass string) } @@ -55,35 +57,71 @@ type Structurer interface { Structure() []Graph } +// MultiStructurer represents a graph.Multigraph that can define subgraphs. +type MultiStructurer interface { + Structure() []Multigraph +} + // Graph wraps named graph.Graph values. type Graph interface { graph.Graph DOTID() string } +// Multigraph wraps named graph.Multigraph values. +type Multigraph interface { + graph.Multigraph + 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. +// MultiSubgrapher wraps graph.Node values that represent subgraphs. +type MultiSubgrapher interface { + Subgraph() graph.Multigraph +} + +// 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. // // 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 +// +// Attributes and IDs are quoted if needed during marshalling. +func Marshal(g graph.Graph, name, prefix, indent string) ([]byte, error) { + var p simpleGraphPrinter 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 +} + +// MarshalMulti returns the DOT encoding for the multigraph 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. +// +// Graph serialization will work for a graph.Multigraph without modification, +// however, advanced GraphViz DOT features provided by Marshal depend on +// implementation of the Node, Attributer, Porter, Attributers, Structurer, +// MultiSubgrapher and Multigraph interfaces. +// +// Attributes and IDs are quoted if needed during marshalling. +func MarshalMulti(g graph.Multigraph, name, prefix, indent string) ([]byte, error) { + var p multiGraphPrinter + p.indent = indent + p.prefix = prefix + p.visited = make(map[line]bool) err := p.print(g, name, false, false) if err != nil { return nil, err @@ -98,8 +136,6 @@ type printer struct { indent string depth int - visited map[edge]bool - err error } @@ -108,35 +144,16 @@ type edge struct { from, to int64 } -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") - +func (p *simpleGraphPrinter) print(g graph.Graph, name string, needsIndent, isSubgraph bool) error { if name == "" { if g, ok := g.(Graph); ok { name = g.DOTID() } } - if name != "" { - p.buf.WriteByte(' ') - p.buf.WriteString(name) - } - p.openBlock(" {") + _, isDirected := g.(graph.Directed) + p.printFrontMatter(name, needsIndent, isSubgraph, isDirected, true) + if a, ok := g.(Attributers); ok { p.writeAttributeComplex(a) } @@ -151,12 +168,15 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool } } + nodes := graph.NodesOf(g.Nodes()) + sort.Sort(ordered.ByID(nodes)) + 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.ID())) == 0 { + if g.From(n.ID()).Len() == 0 { g := s.Subgraph() _, subIsDirected := g.(graph.Directed) if subIsDirected != isDirected { @@ -188,7 +208,7 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool havePrintedEdgeHeader := false for _, n := range nodes { nid := n.ID() - to := g.From(nid) + to := graph.NodesOf(g.From(nid)) sort.Sort(ordered.ByID(to)) for _, t := range to { tid := t.ID() @@ -265,19 +285,48 @@ func (p *printer) print(g graph.Graph, name string, needsIndent, isSubgraph bool p.buf.WriteByte(';') } } + p.closeBlock("}") return nil } +func (p *printer) printFrontMatter(name string, needsIndent, isSubgraph, isDirected, isStrict bool) error { + p.buf.WriteString(p.prefix) + if needsIndent { + for i := 0; i < p.depth; i++ { + p.buf.WriteString(p.indent) + } + } + + if !isSubgraph && isStrict { + p.buf.WriteString("strict ") + } + + if isSubgraph { + p.buf.WriteString("sub") + } else if isDirected { + p.buf.WriteString("di") + } + p.buf.WriteString("graph") + + if name != "" { + p.buf.WriteByte(' ') + p.buf.WriteString(quoteID(name)) + } + + p.openBlock(" {") + return nil +} + func (p *printer) writeNode(n graph.Node) { - p.buf.WriteString(nodeID(n)) + p.buf.WriteString(quoteID(nodeID(n))) } func (p *printer) writePorts(port, cp string) { if port != "" { p.buf.WriteByte(':') - p.buf.WriteString(port) + p.buf.WriteString(quoteID(port)) } if cp != "" { p.buf.WriteByte(':') @@ -294,7 +343,7 @@ func nodeID(n graph.Node) string { } } -func graphID(g graph.Graph, n graph.Node) string { +func graphID(g interface{}, n graph.Node) string { switch g := g.(type) { case Node: return g.DOTID() @@ -309,17 +358,17 @@ func (p *printer) writeAttributeList(a encoding.Attributer) { case 0: case 1: p.buf.WriteString(" [") - p.buf.WriteString(attributes[0].Key) + p.buf.WriteString(quoteID(attributes[0].Key)) p.buf.WriteByte('=') - p.buf.WriteString(attributes[0].Value) + p.buf.WriteString(quoteID(attributes[0].Value)) p.buf.WriteString("]") default: p.openBlock(" [") for _, att := range attributes { p.newline() - p.buf.WriteString(att.Key) + p.buf.WriteString(quoteID(att.Key)) p.buf.WriteByte('=') - p.buf.WriteString(att.Value) + p.buf.WriteString(quoteID(att.Value)) } p.closeBlock("]") } @@ -343,9 +392,9 @@ func (p *printer) writeAttributeComplex(ca Attributers) { p.openBlock(" [") for _, att := range attributes { p.newline() - p.buf.WriteString(att.Key) + p.buf.WriteString(quoteID(att.Key)) p.buf.WriteByte('=') - p.buf.WriteString(att.Value) + p.buf.WriteString(quoteID(att.Value)) } p.closeBlock("]") haveWrittenBlock = true @@ -373,3 +422,236 @@ func (p *printer) closeBlock(b string) { p.newline() p.buf.WriteString(b) } + +type simpleGraphPrinter struct { + printer + visited map[edge]bool +} + +type multiGraphPrinter struct { + printer + visited map[line]bool +} + +type line struct { + inGraph string + id int64 +} + +func (p *multiGraphPrinter) print(g graph.Multigraph, name string, needsIndent, isSubgraph bool) error { + if name == "" { + if g, ok := g.(Multigraph); ok { + name = g.DOTID() + } + } + + _, isDirected := g.(graph.Directed) + p.printFrontMatter(name, needsIndent, isSubgraph, isDirected, false) + + if a, ok := g.(Attributers); ok { + p.writeAttributeComplex(a) + } + if s, ok := g.(MultiStructurer); 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) + } + } + + nodes := graph.NodesOf(g.Nodes()) + sort.Sort(ordered.ByID(nodes)) + + havePrintedNodeHeader := false + for _, n := range nodes { + if s, ok := n.(MultiSubgrapher); ok { + // If the node is not linked to any other node + // the graph needs to be written now. + if g.From(n.ID()).Len() == 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.(encoding.Attributer); ok { + p.writeAttributeList(a) + } + p.buf.WriteByte(';') + } + + havePrintedEdgeHeader := false + for _, n := range nodes { + nid := n.ID() + to := graph.NodesOf(g.From(nid)) + sort.Sort(ordered.ByID(to)) + + for _, t := range to { + tid := t.ID() + + lines := graph.LinesOf(g.Lines(nid, tid)) + sort.Sort(ordered.LinesByIDs(lines)) + + for _, l := range lines { + lid := l.ID() + if p.visited[line{inGraph: name, id: lid}] { + continue + } + p.visited[line{inGraph: name, id: lid}] = 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.(MultiSubgrapher); 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) + } + + porter, edgeIsPorter := l.(Porter) + if edgeIsPorter { + if l.From().ID() == nid { + p.writePorts(porter.FromPort()) + } else { + p.writePorts(porter.ToPort()) + } + } + + if isDirected { + p.buf.WriteString(" -> ") + } else { + p.buf.WriteString(" -- ") + } + + if s, ok := t.(MultiSubgrapher); 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 { + if l.From().ID() == nid { + p.writePorts(porter.ToPort()) + } else { + p.writePorts(porter.FromPort()) + } + } + + if a, ok := l.(encoding.Attributer); ok { + p.writeAttributeList(a) + } + + p.buf.WriteByte(';') + } + } + } + + p.closeBlock("}") + + return nil +} + +// quoteID quotes the given string if needed in the context of an ID. If s is +// already quoted, or if s does not contain any spaces or special characters +// that need escaping, the original string is returned. +func quoteID(s string) string { + // To use a keyword as an ID, it must be quoted. + if isKeyword(s) { + return strconv.Quote(s) + } + // Quote if s is not an ID. This includes strings containing spaces, except + // if those spaces are used within HTML string IDs (e.g. ). + if !isID(s) { + return strconv.Quote(s) + } + return s +} + +// isKeyword reports whether the given string is a keyword in the DOT language. +func isKeyword(s string) bool { + // ref: https://www.graphviz.org/doc/info/lang.html + keywords := []string{"node", "edge", "graph", "digraph", "subgraph", "strict"} + for _, keyword := range keywords { + if strings.EqualFold(s, keyword) { + return true + } + } + return false +} + +// FIXME: see if we rewrite this in another way to remove our regexp dependency. + +// Regular expression to match identifier and numeral IDs. +var ( + reIdent = regexp.MustCompile(`^[a-zA-Z\200-\377_][0-9a-zA-Z\200-\377_]*$`) + reNumeral = regexp.MustCompile(`^[-]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)$`) +) + +// isID reports whether the given string is an ID. +// +// 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 (<...>). +func isID(s string) bool { + // 1. an identifier. + if reIdent.MatchString(s) { + return true + } + // 2. a numeral. + if reNumeral.MatchString(s) { + return true + } + // 3. double-quote string ID. + if len(s) >= 2 && strings.HasPrefix(s, `"`) && strings.HasSuffix(s, `"`) { + // Check that escape sequences within the double-quotes are valid. + if _, err := strconv.Unquote(s); err == nil { + return true + } + } + // 4. HTML ID. + return isHTMLID(s) +} + +// isHTMLID reports whether the given string an HTML ID. +func isHTMLID(s string) bool { + // HTML IDs have the format /^<.*>$/ + return len(s) >= 2 && strings.HasPrefix(s, "<") && strings.HasSuffix(s, ">") +} diff --git a/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go b/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go index 33bda7eb255..53ef0d56c1e 100644 --- a/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go +++ b/vendor/gonum.org/v1/gonum/graph/encoding/encoding.go @@ -12,6 +12,12 @@ type Builder interface { graph.Builder } +// MultiBuilder is a graph that can have user-defined nodes and edges added. +type MultiBuilder interface { + graph.Multigraph + graph.MultigraphBuilder +} + // AttributeSetter is implemented by types that can set an encoded graph // attribute. type AttributeSetter interface { diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go index 7b640a0dc75..ecbef4c6dec 100644 --- a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/errors/errors.go @@ -13,8 +13,8 @@ package errors import ( - "bytes" "fmt" + "strings" "gonum.org/v1/gonum/graph/formats/dot/internal/token" ) @@ -31,7 +31,7 @@ type Error struct { } func (e *Error) String() string { - w := new(bytes.Buffer) + w := new(strings.Builder) fmt.Fprintf(w, "Error") if e.Err != nil { fmt.Fprintf(w, " %s\n", e.Err) @@ -52,7 +52,7 @@ func (e *Error) String() string { } func (e *Error) Error() string { - w := new(bytes.Buffer) + w := new(strings.Builder) 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, ": %+v", e.Err) diff --git a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go index 4c54b469578..52e49513b67 100644 --- a/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go +++ b/vendor/gonum.org/v1/gonum/graph/formats/dot/internal/parser/parser.go @@ -13,8 +13,8 @@ package parser import ( - "bytes" "fmt" + "strings" parseError "gonum.org/v1/gonum/graph/formats/dot/internal/errors" "gonum.org/v1/gonum/graph/formats/dot/internal/token" @@ -76,7 +76,7 @@ func (s *stack) popN(items int) []Attrib { } func (s *stack) String() string { - w := new(bytes.Buffer) + w := new(strings.Builder) fmt.Fprintf(w, "stack:\n") for i, st := range s.state { fmt.Fprintf(w, "\t%d: %d , ", i, st) diff --git a/vendor/gonum.org/v1/gonum/graph/graph.go b/vendor/gonum.org/v1/gonum/graph/graph.go index 3dc3a87531d..c973583d87f 100644 --- a/vendor/gonum.org/v1/gonum/graph/graph.go +++ b/vendor/gonum.org/v1/gonum/graph/graph.go @@ -13,8 +13,15 @@ type Node interface { // edge is given from -> to, otherwise the edge is semantically // unordered. type Edge interface { + // From returns the from node of the edge. From() Node + + // To returns the to node of the edge. To() Node + + // ReversedEdge returns an edge that has + // the end points of the receiver swapped. + ReversedEdge() Edge } // WeightedEdge is a weighted graph edge. In directed graphs, the direction @@ -27,16 +34,20 @@ type WeightedEdge interface { // Graph is a generalized graph. type Graph interface { - // Has returns whether a node with the given ID exists - // within the graph. - Has(id int64) bool + // Node returns the node with the given ID if it exists + // in the graph, and nil otherwise. + Node(id int64) Node // Nodes returns all the nodes in the graph. - Nodes() []Node + // + // Nodes must not return nil. + Nodes() Nodes // From returns all nodes that can be reached directly // from the node with the given ID. - From(id int64) []Node + // + // From must not return nil. + From(id int64) Nodes // HasEdgeBetween returns whether an edge exists between // nodes with IDs xid and yid without considering direction. @@ -99,7 +110,9 @@ type Directed interface { // To returns all nodes that can reach directly // to the node with the given ID. - To(id int64) []Node + // + // To must not return nil. + To(id int64) Nodes } // WeightedDirected is a weighted directed graph. @@ -113,7 +126,9 @@ type WeightedDirected interface { // To returns all nodes that can reach directly // to the node with the given ID. - To(id int64) []Node + // + // To must not return nil. + To(id int64) Nodes } // NodeAdder is an interface for adding arbitrary nodes to a graph. @@ -122,7 +137,7 @@ type NodeAdder interface { // arbitrary ID. NewNode() Node - // Adds a node to the graph. AddNode panics if + // AddNode adds a node to the graph. AddNode panics if // the added node ID matches an existing node ID. AddNode(Node) } @@ -146,8 +161,10 @@ type EdgeAdder interface { // will be added if they do not exist, otherwise // SetEdge will panic. // The behavior of an EdgeAdder when the IDs - // returned by e.From and e.To are equal is + // returned by e.From() and e.To() are equal is // implementation-dependent. + // Whether e, e.From() and e.To() are stored + // within the graph is implementation dependent. SetEdge(e Edge) } @@ -162,8 +179,10 @@ type WeightedEdgeAdder interface { // the nodes will be added if they do not exist, // otherwise SetWeightedEdge will panic. // The behavior of a WeightedEdgeAdder when the IDs - // returned by e.From and e.To are equal is + // returned by e.From() and e.To() are equal is // implementation-dependent. + // Whether e, e.From() and e.To() are stored + // within the graph is implementation dependent. SetWeightedEdge(e WeightedEdge) } @@ -219,12 +238,17 @@ type DirectedWeightedBuilder interface { // be present in the destination after the copy is complete. func Copy(dst Builder, src Graph) { nodes := src.Nodes() - for _, n := range nodes { - dst.AddNode(n) + for nodes.Next() { + dst.AddNode(nodes.Node()) } - for _, u := range nodes { - for _, v := range src.From(u.ID()) { - dst.SetEdge(dst.NewEdge(u, v)) + nodes.Reset() + for nodes.Next() { + u := nodes.Node() + uid := u.ID() + to := src.From(uid) + for to.Next() { + v := to.Node() + dst.SetEdge(src.Edge(uid, v.ID())) } } } @@ -242,12 +266,17 @@ func Copy(dst Builder, src Graph) { // to resolve such conflicts, an UndirectWeighted may be used to do this. func CopyWeighted(dst WeightedBuilder, src Weighted) { nodes := src.Nodes() - for _, n := range nodes { - dst.AddNode(n) + for nodes.Next() { + dst.AddNode(nodes.Node()) } - for _, u := range nodes { - for _, v := range src.From(u.ID()) { - dst.SetWeightedEdge(dst.NewWeightedEdge(u, v, src.WeightedEdge(u.ID(), v.ID()).Weight())) + nodes.Reset() + for nodes.Next() { + u := nodes.Node() + uid := u.ID() + to := src.From(uid) + for to.Next() { + v := to.Node() + dst.SetWeightedEdge(src.WeightedEdge(uid, v.ID())) } } } diff --git a/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go b/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go index ea79993167c..a7250d1f377 100644 --- a/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go +++ b/vendor/gonum.org/v1/gonum/graph/internal/ordered/sort.go @@ -74,3 +74,20 @@ func Reverse(nodes []graph.Node) { nodes[i], nodes[j] = nodes[j], nodes[i] } } + +// LinesByIDs implements the sort.Interface sorting a slice of graph.LinesByIDs +// lexically by the From IDs, then by the To IDs, finally by the Line IDs. +type LinesByIDs []graph.Line + +func (n LinesByIDs) Len() int { return len(n) } +func (n LinesByIDs) Less(i, j int) bool { + a, b := n[i], n[j] + if a.From().ID() != b.From().ID() { + return a.From().ID() < b.From().ID() + } + if a.To().ID() != b.To().ID() { + return a.To().ID() < b.To().ID() + } + return n[i].ID() < n[j].ID() +} +func (n LinesByIDs) Swap(i, j int) { n[i], n[j] = n[j], n[i] } diff --git a/vendor/gonum.org/v1/gonum/graph/internal/set/set.go b/vendor/gonum.org/v1/gonum/graph/internal/set/set.go index aacff164145..0506b8e97d4 100644 --- a/vendor/gonum.org/v1/gonum/graph/internal/set/set.go +++ b/vendor/gonum.org/v1/gonum/graph/internal/set/set.go @@ -103,6 +103,16 @@ func Int64sEqual(a, b Int64s) bool { // Nodes is a set of nodes keyed in their integer identifiers. type Nodes map[int64]graph.Node +// NewNodes returns a new Nodes. +func NewNodes() Nodes { + return make(Nodes) +} + +// NewNodes returns a new Nodes with the given size hint, n. +func NewNodesSize(n int) Nodes { + return make(Nodes, n) +} + // The simple accessor methods for Nodes are provided to allow ease of // implementation change should the need arise. @@ -116,34 +126,23 @@ func (s Nodes) Remove(e graph.Node) { delete(s, e.ID()) } -// Has reports the existence of the element in the set. +// Count returns the number of element in the set. +func (s Nodes) Count() int { + return len(s) +} + +// Has reports the existence of the elements 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)) - } - +// CloneNodes returns a clone of src. +func CloneNodes(src Nodes) Nodes { + dst := make(Nodes, len(src)) for e, n := range src { dst[e] = n } - return dst } @@ -167,7 +166,7 @@ func Equal(a, b Nodes) bool { return true } -// Union takes the union of a and b, and stores it in dst. +// UnionOfNodes returns the union of a and b. // // The union of two sets, a and b, is the set containing all the // elements of each, for instance: @@ -179,31 +178,23 @@ func Equal(a, b Nodes) bool { // // {a,b,c} UNION {b,c,d} = {a,b,c,d} // -func (dst Nodes) Union(a, b Nodes) Nodes { +func UnionOfNodes(a, b Nodes) Nodes { if same(a, b) { - return dst.Copy(a) + return CloneNodes(a) } - if !same(a, dst) && !same(b, dst) { - dst.clear() + dst := make(Nodes) + for e, n := range a { + dst[e] = n } - - if !same(dst, a) { - for e, n := range a { - dst[e] = n - } - } - - if !same(dst, b) { - for e, n := range b { - dst[e] = n - } + for e, n := range b { + dst[e] = n } return dst } -// Intersect takes the intersection of a and b, and stores it in dst. +// IntersectionOfNodes returns the intersection of a and b. // // The intersection of two sets, a and b, is the set containing all // the elements shared between the two sets, for instance: @@ -220,37 +211,18 @@ func (dst Nodes) Union(a, b Nodes) Nodes { // // {a,b,c} INTERSECT {d,e,f} = {} // -func (dst Nodes) Intersect(a, b Nodes) Nodes { - var swap Nodes - +func IntersectionOfNodes(a, b Nodes) Nodes { if same(a, b) { - return dst.Copy(a) + return CloneNodes(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 + dst := make(Nodes) + if len(a) > len(b) { + a, b = b, a } - - for e := range dst { - if _, ok := swap[e]; !ok { - delete(dst, e) + for e, n := range a { + if _, ok := b[e]; ok { + dst[e] = n } } - return dst } diff --git a/vendor/gonum.org/v1/gonum/graph/iterator/BUILD b/vendor/gonum.org/v1/gonum/graph/iterator/BUILD new file mode 100644 index 00000000000..3e272588796 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/iterator/BUILD @@ -0,0 +1,29 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "edges.go", + "lines.go", + "nodes.go", + ], + importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/graph/iterator", + importpath = "gonum.org/v1/gonum/graph/iterator", + visibility = ["//visibility:public"], + deps = ["//vendor/gonum.org/v1/gonum/graph:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/gonum.org/v1/gonum/graph/iterator/doc.go b/vendor/gonum.org/v1/gonum/graph/iterator/doc.go new file mode 100644 index 00000000000..0983bc7c361 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/iterator/doc.go @@ -0,0 +1,9 @@ +// Copyright ©2018 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package iterator provides node, edge and line iterators. +// +// The iterators provided satisfy the graph.Nodes, graph.Edges and +// graph.Lines interfaces. +package iterator diff --git a/vendor/gonum.org/v1/gonum/graph/iterator/edges.go b/vendor/gonum.org/v1/gonum/graph/iterator/edges.go new file mode 100644 index 00000000000..21ef0433e81 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/iterator/edges.go @@ -0,0 +1,131 @@ +// Copyright ©2018 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package iterator + +import "gonum.org/v1/gonum/graph" + +// OrderedEdges implements the graph.Edges and graph.EdgeSlicer interfaces. +// The iteration order of OrderedEdges is the order of edges passed to +// NewEdgeIterator. +type OrderedEdges struct { + idx int + edges []graph.Edge +} + +// NewOrderedEdges returns an OrderedEdges initialized with the provided edges. +func NewOrderedEdges(edges []graph.Edge) *OrderedEdges { + return &OrderedEdges{idx: -1, edges: edges} +} + +// Len returns the remaining number of edges to be iterated over. +func (e *OrderedEdges) Len() int { + if e.idx >= len(e.edges) { + return 0 + } + if e.idx <= 0 { + return len(e.edges) + } + return len(e.edges[e.idx:]) +} + +// Next returns whether the next call of Edge will return a valid edge. +func (e *OrderedEdges) Next() bool { + if uint(e.idx)+1 < uint(len(e.edges)) { + e.idx++ + return true + } + e.idx = len(e.edges) + return false +} + +// Edge returns the current edge of the iterator. Next must have been +// called prior to a call to Edge. +func (e *OrderedEdges) Edge() graph.Edge { + if e.idx >= len(e.edges) || e.idx < 0 { + return nil + } + return e.edges[e.idx] +} + +// EdgeSlice returns all the remaining edges in the iterator and advances +// the iterator. +func (e *OrderedEdges) EdgeSlice() []graph.Edge { + if e.idx >= len(e.edges) { + return nil + } + idx := e.idx + if idx == -1 { + idx = 0 + } + e.idx = len(e.edges) + return e.edges[idx:] +} + +// Reset returns the iterator to its initial state. +func (e *OrderedEdges) Reset() { + e.idx = -1 +} + +// OrderedWeightedEdges implements the graph.Edges and graph.EdgeSlicer interfaces. +// The iteration order of OrderedWeightedEdges is the order of edges passed to +// NewEdgeIterator. +type OrderedWeightedEdges struct { + idx int + edges []graph.WeightedEdge +} + +// NewOrderedWeightedEdges returns an OrderedWeightedEdges initialized with the provided edges. +func NewOrderedWeightedEdges(edges []graph.WeightedEdge) *OrderedWeightedEdges { + return &OrderedWeightedEdges{idx: -1, edges: edges} +} + +// Len returns the remaining number of edges to be iterated over. +func (e *OrderedWeightedEdges) Len() int { + if e.idx >= len(e.edges) { + return 0 + } + if e.idx <= 0 { + return len(e.edges) + } + return len(e.edges[e.idx:]) +} + +// Next returns whether the next call of WeightedEdge will return a valid edge. +func (e *OrderedWeightedEdges) Next() bool { + if uint(e.idx)+1 < uint(len(e.edges)) { + e.idx++ + return true + } + e.idx = len(e.edges) + return false +} + +// WeightedEdge returns the current edge of the iterator. Next must have been +// called prior to a call to WeightedEdge. +func (e *OrderedWeightedEdges) WeightedEdge() graph.WeightedEdge { + if e.idx >= len(e.edges) || e.idx < 0 { + return nil + } + return e.edges[e.idx] +} + +// WeightedEdgeSlice returns all the remaining edges in the iterator and advances +// the iterator. +func (e *OrderedWeightedEdges) WeightedEdgeSlice() []graph.WeightedEdge { + if e.idx >= len(e.edges) { + return nil + } + idx := e.idx + if idx == -1 { + idx = 0 + } + e.idx = len(e.edges) + return e.edges[idx:] +} + +// Reset returns the iterator to its initial state. +func (e *OrderedWeightedEdges) Reset() { + e.idx = -1 +} diff --git a/vendor/gonum.org/v1/gonum/graph/iterator/lines.go b/vendor/gonum.org/v1/gonum/graph/iterator/lines.go new file mode 100644 index 00000000000..ed655df0162 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/iterator/lines.go @@ -0,0 +1,131 @@ +// Copyright ©2018 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package iterator + +import "gonum.org/v1/gonum/graph" + +// OrderedLines implements the graph.Lines and graph.LineSlicer interfaces. +// The iteration order of OrderedLines is the order of lines passed to +// NewLineIterator. +type OrderedLines struct { + idx int + lines []graph.Line +} + +// NewOrderedLines returns an OrderedLines initialized with the provided lines. +func NewOrderedLines(lines []graph.Line) *OrderedLines { + return &OrderedLines{idx: -1, lines: lines} +} + +// Len returns the remaining number of lines to be iterated over. +func (e *OrderedLines) Len() int { + if e.idx >= len(e.lines) { + return 0 + } + if e.idx <= 0 { + return len(e.lines) + } + return len(e.lines[e.idx:]) +} + +// Next returns whether the next call of Line will return a valid line. +func (e *OrderedLines) Next() bool { + if uint(e.idx)+1 < uint(len(e.lines)) { + e.idx++ + return true + } + e.idx = len(e.lines) + return false +} + +// Line returns the current line of the iterator. Next must have been +// called prior to a call to Line. +func (e *OrderedLines) Line() graph.Line { + if e.idx >= len(e.lines) || e.idx < 0 { + return nil + } + return e.lines[e.idx] +} + +// LineSlice returns all the remaining lines in the iterator and advances +// the iterator. +func (e *OrderedLines) LineSlice() []graph.Line { + if e.idx >= len(e.lines) { + return nil + } + idx := e.idx + if idx == -1 { + idx = 0 + } + e.idx = len(e.lines) + return e.lines[idx:] +} + +// Reset returns the iterator to its initial state. +func (e *OrderedLines) Reset() { + e.idx = -1 +} + +// OrderedWeightedLines implements the graph.Lines and graph.LineSlicer interfaces. +// The iteration order of OrderedWeightedLines is the order of lines passed to +// NewLineIterator. +type OrderedWeightedLines struct { + idx int + lines []graph.WeightedLine +} + +// NewWeightedLineIterator returns an OrderedWeightedLines initialized with the provided lines. +func NewOrderedWeightedLines(lines []graph.WeightedLine) *OrderedWeightedLines { + return &OrderedWeightedLines{idx: -1, lines: lines} +} + +// Len returns the remaining number of lines to be iterated over. +func (e *OrderedWeightedLines) Len() int { + if e.idx >= len(e.lines) { + return 0 + } + if e.idx <= 0 { + return len(e.lines) + } + return len(e.lines[e.idx:]) +} + +// Next returns whether the next call of WeightedLine will return a valid line. +func (e *OrderedWeightedLines) Next() bool { + if uint(e.idx)+1 < uint(len(e.lines)) { + e.idx++ + return true + } + e.idx = len(e.lines) + return false +} + +// WeightedLine returns the current line of the iterator. Next must have been +// called prior to a call to WeightedLine. +func (e *OrderedWeightedLines) WeightedLine() graph.WeightedLine { + if e.idx >= len(e.lines) || e.idx < 0 { + return nil + } + return e.lines[e.idx] +} + +// WeightedLineSlice returns all the remaining lines in the iterator and advances +// the iterator. +func (e *OrderedWeightedLines) WeightedLineSlice() []graph.WeightedLine { + if e.idx >= len(e.lines) { + return nil + } + idx := e.idx + if idx == -1 { + idx = 0 + } + e.idx = len(e.lines) + return e.lines[idx:] +} + +// Reset returns the iterator to its initial state. +func (e *OrderedWeightedLines) Reset() { + e.idx = -1 +} diff --git a/vendor/gonum.org/v1/gonum/graph/iterator/nodes.go b/vendor/gonum.org/v1/gonum/graph/iterator/nodes.go new file mode 100644 index 00000000000..952dd770f2e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/iterator/nodes.go @@ -0,0 +1,125 @@ +// Copyright ©2018 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package iterator + +import "gonum.org/v1/gonum/graph" + +// OrderedNodes implements the graph.Nodes and graph.NodeSlicer interfaces. +// The iteration order of OrderedNodes is the order of nodes passed to +// NewNodeIterator. +type OrderedNodes struct { + idx int + nodes []graph.Node +} + +// NewOrderedNodes returns a OrderedNodes initialized with the provided nodes. +func NewOrderedNodes(nodes []graph.Node) *OrderedNodes { + return &OrderedNodes{idx: -1, nodes: nodes} +} + +// Len returns the remaining number of nodes to be iterated over. +func (n *OrderedNodes) Len() int { + if n.idx >= len(n.nodes) { + return 0 + } + if n.idx <= 0 { + return len(n.nodes) + } + return len(n.nodes[n.idx:]) +} + +// Next returns whether the next call of Node will return a valid node. +func (n *OrderedNodes) Next() bool { + if uint(n.idx)+1 < uint(len(n.nodes)) { + n.idx++ + return true + } + n.idx = len(n.nodes) + return false +} + +// Node returns the current node of the iterator. Next must have been +// called prior to a call to Node. +func (n *OrderedNodes) Node() graph.Node { + if n.idx >= len(n.nodes) || n.idx < 0 { + return nil + } + return n.nodes[n.idx] +} + +// NodeSlice returns all the remaining nodes in the iterator and advances +// the iterator. +func (n *OrderedNodes) NodeSlice() []graph.Node { + if n.idx >= len(n.nodes) { + return nil + } + idx := n.idx + if idx == -1 { + idx = 0 + } + n.idx = len(n.nodes) + return n.nodes[idx:] +} + +// Reset returns the iterator to its initial state. +func (n *OrderedNodes) Reset() { + n.idx = -1 +} + +// ImplicitNodes implements the graph.Nodes interface for a set of nodes over +// a contiguous ID range. +type ImplicitNodes struct { + beg, end int + curr int + newNode func(id int) graph.Node +} + +// NewImplicitNodes returns a new implicit node iterator spanning nodes in [beg,end). +// The provided new func maps the id to a graph.Node. NewImplicitNodes will panic +// if beg is greater than end. +func NewImplicitNodes(beg, end int, new func(id int) graph.Node) *ImplicitNodes { + if beg > end { + panic("iterator: invalid range") + } + return &ImplicitNodes{beg: beg, end: end, curr: beg - 1, newNode: new} +} + +// Len returns the remaining number of nodes to be iterated over. +func (n *ImplicitNodes) Len() int { + return n.end - n.curr - 1 +} + +// Next returns whether the next call of Node will return a valid node. +func (n *ImplicitNodes) Next() bool { + if n.curr == n.end { + return false + } + n.curr++ + return n.curr < n.end +} + +// Node returns the current node of the iterator. Next must have been +// called prior to a call to Node. +func (n *ImplicitNodes) Node() graph.Node { + if n.Len() == -1 || n.curr < n.beg { + return nil + } + return n.newNode(n.curr) +} + +// Reset returns the iterator to its initial state. +func (n *ImplicitNodes) Reset() { + n.curr = n.beg - 1 +} + +// NodeSlice returns all the remaining nodes in the iterator and advances +// the iterator. +func (n *ImplicitNodes) NodeSlice() []graph.Node { + nodes := make([]graph.Node, 0, n.Len()) + for n.curr++; n.curr < n.end; n.curr++ { + nodes = append(nodes, n.newNode(n.curr)) + } + return nodes +} diff --git a/vendor/gonum.org/v1/gonum/graph/multigraph.go b/vendor/gonum.org/v1/gonum/graph/multigraph.go index d558fbc7160..038a3d515f5 100644 --- a/vendor/gonum.org/v1/gonum/graph/multigraph.go +++ b/vendor/gonum.org/v1/gonum/graph/multigraph.go @@ -7,7 +7,17 @@ package graph // Line is an edge in a multigraph. A Line returns an ID that must // distinguish Lines sharing Node end points. type Line interface { - Edge + // From returns the from node of the edge. + From() Node + + // To returns the to node of the edge. + To() Node + + // ReversedLine returns a line that has the + // end points of the receiver swapped. + ReversedLine() Line + + // ID returns the unique ID for the Line. ID() int64 } @@ -19,16 +29,20 @@ type WeightedLine interface { // Multigraph is a generalized multigraph. type Multigraph interface { - // Has returns whether the node with the given ID exists - // within the multigraph. - Has(id int64) bool + // Node returns the node with the given ID if it exists + // in the multigraph, and nil otherwise. + Node(id int64) Node // Nodes returns all the nodes in the multigraph. - Nodes() []Node + // + // Nodes must not return nil. + Nodes() Nodes // From returns all nodes that can be reached directly // from the node with the given ID. - From(id int64) []Node + // + // From must not return nil. + From(id int64) Nodes // HasEdgeBetween returns whether an edge exists between // nodes with IDs xid and yid without considering direction. @@ -38,7 +52,9 @@ type Multigraph interface { // vid, if any such lines exist and nil otherwise. The // node v must be directly reachable from u as defined by // the From method. - Lines(uid, vid int64) []Line + // + // Lines must not return nil. + Lines(uid, vid int64) Lines } // WeightedMultigraph is a weighted multigraph. @@ -49,7 +65,9 @@ type WeightedMultigraph interface { // with IDs uid and vid if any such lines exist and nil // otherwise. The node v must be directly reachable // from u as defined by the From method. - WeightedLines(uid, vid int64) []WeightedLine + // + // WeightedLines must not return nil. + WeightedLines(uid, vid int64) WeightedLines } // UndirectedMultigraph is an undirected multigraph. @@ -58,7 +76,9 @@ type UndirectedMultigraph interface { // LinesBetween returns the lines between nodes x and y // with IDs xid and yid. - LinesBetween(xid, yid int64) []Line + // + // LinesBetween must not return nil. + LinesBetween(xid, yid int64) Lines } // WeightedUndirectedMultigraph is a weighted undirected multigraph. @@ -67,7 +87,9 @@ type WeightedUndirectedMultigraph interface { // WeightedLinesBetween returns the lines between nodes // x and y with IDs xid and yid. - WeightedLinesBetween(xid, yid int64) []WeightedLine + // + // WeightedLinesBetween must not return nil. + WeightedLinesBetween(xid, yid int64) WeightedLines } // DirectedMultigraph is a directed multigraph. @@ -81,7 +103,9 @@ type DirectedMultigraph interface { // To returns all nodes that can reach directly // to the node with the given ID. - To(id int64) []Node + // + // To must not return nil. + To(id int64) Nodes } // WeightedDirectedMultigraph is a weighted directed multigraph. @@ -95,7 +119,9 @@ type WeightedDirectedMultigraph interface { // To returns all nodes that can reach directly // to the node with the given ID. - To(id int64) []Node + // + // To must not return nil. + To(id int64) Nodes } // LineAdder is an interface for adding lines to a multigraph. @@ -107,6 +133,8 @@ type LineAdder interface { // If the multigraph supports node addition the nodes // will be added if they do not exist, otherwise // SetLine will panic. + // Whether l, l.From() and l.To() are stored + // within the graph is implementation dependent. SetLine(l Line) } @@ -120,7 +148,9 @@ type WeightedLineAdder interface { // to another. If the multigraph supports node addition // the nodes will be added if they do not exist, // otherwise SetWeightedLine will panic. - SetWeightedLine(e WeightedLine) + // Whether l, l.From() and l.To() are stored + // within the graph is implementation dependent. + SetWeightedLine(l WeightedLine) } // LineRemover is an interface for removing lines from a multigraph. diff --git a/vendor/gonum.org/v1/gonum/graph/nodes_edges.go b/vendor/gonum.org/v1/gonum/graph/nodes_edges.go new file mode 100644 index 00000000000..3d5dae1fa1d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/graph/nodes_edges.go @@ -0,0 +1,300 @@ +// Copyright ©2018 The Gonum Authors. 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 + +// Iterator is an item iterator. +type Iterator interface { + // Next advances the iterator and returns whether + // the next call to the item method will return a + // non-nil item. + // + // Next should be called prior to any call to the + // iterator's item retrieval method after the + // iterator has been obtained or reset. + // + // The order of iteration is implementation + // dependent. + Next() bool + + // Len returns the number of items remaining in the + // iterator. + // + // If the number of items in the iterator is unknown, + // too large to materialize or too costly to calculate + // then Len may return a negative value. + // In this case the consuming function must be able + // to operate on the items of the iterator directly + // without materializing the items into a slice. + // The magnitude of a negative length has + // implementation-dependent semantics. + Len() int + + // Reset returns the iterator to its start position. + Reset() +} + +// Nodes is a Node iterator. +type Nodes interface { + Iterator + + // Node returns the current Node from the iterator. + Node() Node +} + +// NodeSlicer wraps the NodeSlice method. +type NodeSlicer interface { + // NodeSlice returns the set of nodes remaining + // to be iterated by a Nodes iterator. + // The holder of the iterator may arbitrarily + // change elements in the returned slice, but + // those changes may be reflected to other + // iterators. + NodeSlice() []Node +} + +// NodesOf returns it.Len() nodes from it. If it is a NodeSlicer, the NodeSlice method +// is used to obtain the nodes. It is safe to pass a nil Nodes to NodesOf. +// +// If the Nodes has an indeterminate length, NodesOf will panic. +func NodesOf(it Nodes) []Node { + if it == nil { + return nil + } + len := it.Len() + switch { + case len == 0: + return nil + case len < 0: + panic("graph: called NodesOf on indeterminate iterator") + } + switch it := it.(type) { + case NodeSlicer: + return it.NodeSlice() + } + n := make([]Node, 0, len) + for it.Next() { + n = append(n, it.Node()) + } + return n +} + +// Edges is an Edge iterator. +type Edges interface { + Iterator + + // Edge returns the current Edge from the iterator. + Edge() Edge +} + +// EdgeSlicer wraps the EdgeSlice method. +type EdgeSlicer interface { + // EdgeSlice returns the set of edges remaining + // to be iterated by an Edges iterator. + // The holder of the iterator may arbitrarily + // change elements in the returned slice, but + // those changes may be reflected to other + // iterators. + EdgeSlice() []Edge +} + +// EdgesOf returns it.Len() nodes from it. If it is an EdgeSlicer, the EdgeSlice method is used +// to obtain the edges. It is safe to pass a nil Edges to EdgesOf. +// +// If the Edges has an indeterminate length, EdgesOf will panic. +func EdgesOf(it Edges) []Edge { + if it == nil { + return nil + } + len := it.Len() + switch { + case len == 0: + return nil + case len < 0: + panic("graph: called EdgesOf on indeterminate iterator") + } + switch it := it.(type) { + case EdgeSlicer: + return it.EdgeSlice() + } + e := make([]Edge, 0, len) + for it.Next() { + e = append(e, it.Edge()) + } + return e +} + +// WeightedEdges is a WeightedEdge iterator. +type WeightedEdges interface { + Iterator + + // Edge returns the current Edge from the iterator. + WeightedEdge() WeightedEdge +} + +// WeightedEdgeSlicer wraps the WeightedEdgeSlice method. +type WeightedEdgeSlicer interface { + // EdgeSlice returns the set of edges remaining + // to be iterated by an Edges iterator. + // The holder of the iterator may arbitrarily + // change elements in the returned slice, but + // those changes may be reflected to other + // iterators. + WeightedEdgeSlice() []WeightedEdge +} + +// WeightedEdgesOf returns it.Len() weighted edge from it. If it is a WeightedEdgeSlicer, the +// WeightedEdgeSlice method is used to obtain the edges. It is safe to pass a nil WeightedEdges +// to WeightedEdgesOf. +// +// If the WeightedEdges has an indeterminate length, WeightedEdgesOf will panic. +func WeightedEdgesOf(it WeightedEdges) []WeightedEdge { + if it == nil { + return nil + } + len := it.Len() + switch { + case len == 0: + return nil + case len < 0: + panic("graph: called WeightedEdgesOf on indeterminate iterator") + } + switch it := it.(type) { + case WeightedEdgeSlicer: + return it.WeightedEdgeSlice() + } + e := make([]WeightedEdge, 0, len) + for it.Next() { + e = append(e, it.WeightedEdge()) + } + return e +} + +// Lines is a Line iterator. +type Lines interface { + Iterator + + // Line returns the current Line from the iterator. + Line() Line +} + +// LineSlicer wraps the LineSlice method. +type LineSlicer interface { + // LineSlice returns the set of lines remaining + // to be iterated by an Lines iterator. + // The holder of the iterator may arbitrarily + // change elements in the returned slice, but + // those changes may be reflected to other + // iterators. + LineSlice() []Line +} + +// LinesOf returns it.Len() nodes from it. If it is a LineSlicer, the LineSlice method is used +// to obtain the lines. It is safe to pass a nil Lines to LinesOf. +// +// If the Lines has an indeterminate length, LinesOf will panic. +func LinesOf(it Lines) []Line { + if it == nil { + return nil + } + len := it.Len() + switch { + case len == 0: + return nil + case len < 0: + panic("graph: called LinesOf on indeterminate iterator") + } + switch it := it.(type) { + case LineSlicer: + return it.LineSlice() + } + l := make([]Line, 0, len) + for it.Next() { + l = append(l, it.Line()) + } + return l +} + +// WeightedLines is a WeightedLine iterator. +type WeightedLines interface { + Iterator + + // Line returns the current Line from the iterator. + WeightedLine() WeightedLine +} + +// WeightedLineSlicer wraps the WeightedLineSlice method. +type WeightedLineSlicer interface { + // LineSlice returns the set of lines remaining + // to be iterated by an Lines iterator. + // The holder of the iterator may arbitrarily + // change elements in the returned slice, but + // those changes may be reflected to other + // iterators. + WeightedLineSlice() []WeightedLine +} + +// WeightedLinesOf returns it.Len() weighted line from it. If it is a WeightedLineSlicer, the +// WeightedLineSlice method is used to obtain the lines. It is safe to pass a nil WeightedLines +// to WeightedLinesOf. +// +// If the WeightedLines has an indeterminate length, WeightedLinesOf will panic. +func WeightedLinesOf(it WeightedLines) []WeightedLine { + if it == nil { + return nil + } + len := it.Len() + switch { + case len == 0: + return nil + case len < 0: + panic("graph: called WeightedLinesOf on indeterminate iterator") + } + switch it := it.(type) { + case WeightedLineSlicer: + return it.WeightedLineSlice() + } + l := make([]WeightedLine, 0, len) + for it.Next() { + l = append(l, it.WeightedLine()) + } + return l +} + +// Empty is an empty set of nodes, edges or lines. It should be used when +// a graph returns a zero-length Iterator. Empty implements the slicer +// interfaces for nodes, edges and lines, returning nil for each of these. +const Empty = nothing + +var ( + _ Iterator = Empty + _ Nodes = Empty + _ NodeSlicer = Empty + _ Edges = Empty + _ EdgeSlicer = Empty + _ WeightedEdges = Empty + _ WeightedEdgeSlicer = Empty + _ Lines = Empty + _ LineSlicer = Empty + _ WeightedLines = Empty + _ WeightedLineSlicer = Empty +) + +const nothing = empty(true) + +type empty bool + +func (empty) Next() bool { return false } +func (empty) Len() int { return 0 } +func (empty) Reset() {} +func (empty) Node() Node { return nil } +func (empty) NodeSlice() []Node { return nil } +func (empty) Edge() Edge { return nil } +func (empty) EdgeSlice() []Edge { return nil } +func (empty) WeightedEdge() WeightedEdge { return nil } +func (empty) WeightedEdgeSlice() []WeightedEdge { return nil } +func (empty) Line() Line { return nil } +func (empty) LineSlice() []Line { return nil } +func (empty) WeightedLine() WeightedLine { return nil } +func (empty) WeightedLineSlice() []WeightedLine { return nil } diff --git a/vendor/gonum.org/v1/gonum/graph/simple/BUILD b/vendor/gonum.org/v1/gonum/graph/simple/BUILD index 647def05da6..c8964e8fcd2 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/BUILD +++ b/vendor/gonum.org/v1/gonum/graph/simple/BUILD @@ -19,6 +19,7 @@ go_library( "//vendor/gonum.org/v1/gonum/graph:go_default_library", "//vendor/gonum.org/v1/gonum/graph/internal/ordered:go_default_library", "//vendor/gonum.org/v1/gonum/graph/internal/uid:go_default_library", + "//vendor/gonum.org/v1/gonum/graph/iterator:go_default_library", "//vendor/gonum.org/v1/gonum/mat:go_default_library", ], ) diff --git a/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go b/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go index 717574dbb4a..3daca9adec7 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/dense_directed_matrix.go @@ -9,9 +9,19 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/iterator" "gonum.org/v1/gonum/mat" ) +var ( + dm *DirectedMatrix + + _ graph.Graph = dm + _ graph.Directed = dm + _ edgeSetter = dm + _ weightedEdgeSetter = dm +) + // 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 @@ -63,44 +73,14 @@ func NewDirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *Dire return g } -// Node returns the node in the graph with the given ID. -func (g *DirectedMatrix) Node(id int64) 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(id int64) bool { - return g.has(id) -} - -func (g *DirectedMatrix) has(id int64) bool { - r, _ := g.mat.Dims() - return 0 <= id && id < int64(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 +// 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(uid, vid int64) graph.Edge { + return g.WeightedEdge(uid, vid) } // Edges returns all the edges in the graph. -func (g *DirectedMatrix) Edges() []graph.Edge { +func (g *DirectedMatrix) Edges() graph.Edges { var edges []graph.Edge r, _ := g.mat.Dims() for i := 0; i < r; i++ { @@ -113,15 +93,18 @@ func (g *DirectedMatrix) Edges() []graph.Edge { } } } - return edges + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedEdges(edges) } // From returns all nodes in g that can be reached directly from n. -func (g *DirectedMatrix) From(id int64) []graph.Node { +func (g *DirectedMatrix) From(id int64) graph.Nodes { if !g.has(id) { - return nil + return graph.Empty } - var neighbors []graph.Node + var nodes []graph.Node _, c := g.mat.Dims() for j := 0; j < c; j++ { if int64(j) == id { @@ -129,29 +112,13 @@ func (g *DirectedMatrix) From(id int64) []graph.Node { } // id is not greater than maximum int by this point. if !isSame(g.mat.At(int(id), j), g.absent) { - neighbors = append(neighbors, g.Node(int64(j))) + nodes = append(nodes, g.Node(int64(j))) } } - return neighbors -} - -// To returns all nodes in g that can reach directly to n. -func (g *DirectedMatrix) To(id int64) []graph.Node { - if !g.has(id) { - return nil + if len(nodes) == 0 { + return graph.Empty } - var neighbors []graph.Node - r, _ := g.mat.Dims() - for i := 0; i < r; i++ { - if int64(i) == id { - continue - } - // id is not greater than maximum int by this point. - if !isSame(g.mat.At(i, int(id)), g.absent) { - neighbors = append(neighbors, g.Node(int64(i))) - } - } - return neighbors + return iterator.NewOrderedNodes(nodes) } // HasEdgeBetween returns whether an edge exists between nodes x and y without @@ -167,22 +134,6 @@ func (g *DirectedMatrix) HasEdgeBetween(xid, yid int64) bool { return xid != yid && (!isSame(g.mat.At(int(xid), int(yid)), g.absent) || !isSame(g.mat.At(int(yid), int(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(uid, vid int64) graph.Edge { - return g.WeightedEdge(uid, vid) -} - -// WeightedEdge returns the weighted 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) WeightedEdge(uid, vid int64) graph.WeightedEdge { - if g.HasEdgeFromTo(uid, vid) { - // xid and yid are not greater than maximum int by this point. - return WeightedEdge{F: g.Node(uid), T: g.Node(vid), W: g.mat.At(int(uid), int(vid))} - } - return nil -} - // HasEdgeFromTo returns whether an edge exists in the graph from u to v. func (g *DirectedMatrix) HasEdgeFromTo(uid, vid int64) bool { if !g.has(uid) { @@ -195,47 +146,37 @@ func (g *DirectedMatrix) HasEdgeFromTo(uid, vid int64) bool { return uid != vid && !isSame(g.mat.At(int(uid), int(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(xid, yid int64) (w float64, ok bool) { - if xid == yid { - return g.self, true - } - if g.has(xid) && g.has(yid) { - // xid and yid are not greater than maximum int by this point. - return g.mat.At(int(xid), int(yid)), true - } - return g.absent, false +// Matrix returns the mat.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() mat.Matrix { + // Prevent alteration of dimensions of the returned matrix. + m := *g.mat + return &m } -// SetEdge sets e, an edge from one node to another with unit weight. 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) { - g.setWeightedEdge(e, 1) +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g *DirectedMatrix) Node(id int64) graph.Node { + if !g.has(id) { + return nil + } + if g.nodes == nil { + return Node(id) + } + return g.nodes[id] } -// SetWeightedEdge 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, SetWeightedEdge panics. -func (g *DirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) { - g.setWeightedEdge(e, e.Weight()) -} - -func (g *DirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) { - fid := e.From().ID() - tid := e.To().ID() - if fid == tid { - panic("simple: set illegal edge") +// Nodes returns all the nodes in the graph. +func (g *DirectedMatrix) Nodes() graph.Nodes { + if g.nodes != nil { + nodes := make([]graph.Node, len(g.nodes)) + copy(nodes, g.nodes) + return iterator.NewOrderedNodes(nodes) } - if int64(int(fid)) != fid { - panic("simple: unavailable from node ID for dense graph") - } - if int64(int(tid)) != tid { - panic("simple: unavailable to node ID for dense graph") - } - // fid and tid are not greater than maximum int by this point. - g.mat.Set(int(fid), int(tid), weight) + r, _ := g.mat.Dims() + // Matrix graphs must have at least one node. + return iterator.NewImplicitNodes(0, r, newSimpleNode) } // RemoveEdge removes the edge with the given end point nodes from the graph, leaving the terminal @@ -251,39 +192,110 @@ func (g *DirectedMatrix) RemoveEdge(fid, tid int64) { g.mat.Set(int(fid), int(tid), g.absent) } -// Degree returns the in+out degree of n in g. -func (g *DirectedMatrix) Degree(id int64) int { - if !g.has(id) { - return 0 +// SetEdge sets e, an edge from one node to another with unit weight. If the ends of the edge +// are not in g or the edge is a self loop, SetEdge panics. SetEdge will store the nodes of +// e in the graph if it was initialized with NewDirectedMatrixFrom. +func (g *DirectedMatrix) SetEdge(e graph.Edge) { + g.setWeightedEdge(e, 1) +} + +// SetWeightedEdge 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, SetWeightedEdge panics. SetWeightedEdge will store the nodes of +// e in the graph if it was initialized with NewDirectedMatrixFrom. +func (g *DirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) { + g.setWeightedEdge(e, e.Weight()) +} + +func (g *DirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) { + from := e.From() + fid := from.ID() + to := e.To() + tid := to.ID() + if fid == tid { + panic("simple: set illegal edge") } - var deg int - r, c := g.mat.Dims() + if int64(int(fid)) != fid { + panic("simple: unavailable from node ID for dense graph") + } + if int64(int(tid)) != tid { + panic("simple: unavailable to node ID for dense graph") + } + if g.nodes != nil { + g.nodes[fid] = from + g.nodes[tid] = to + } + // fid and tid are not greater than maximum int by this point. + g.mat.Set(int(fid), int(tid), weight) +} + +// To returns all nodes in g that can reach directly to n. +func (g *DirectedMatrix) To(id int64) graph.Nodes { + if !g.has(id) { + return graph.Empty + } + var nodes []graph.Node + r, _ := g.mat.Dims() for i := 0; i < r; i++ { - if int64(i) == id { - continue - } - // id is not greater than maximum int by this point. - if !isSame(g.mat.At(int(id), i), g.absent) { - deg++ - } - } - for i := 0; i < c; i++ { if int64(i) == id { continue } // id is not greater than maximum int by this point. if !isSame(g.mat.At(i, int(id)), g.absent) { - deg++ + nodes = append(nodes, g.Node(int64(i))) } } - return deg + if len(nodes) == 0 { + return graph.Empty + } + return iterator.NewOrderedNodes(nodes) } -// Matrix returns the mat.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() mat.Matrix { - // Prevent alteration of dimensions of the returned matrix. - m := *g.mat - return &m +// 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(xid, yid int64) (w float64, ok bool) { + if xid == yid { + return g.self, true + } + if g.HasEdgeFromTo(xid, yid) { + // xid and yid are not greater than maximum int by this point. + return g.mat.At(int(xid), int(yid)), true + } + return g.absent, false +} + +// WeightedEdge returns the weighted 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) WeightedEdge(uid, vid int64) graph.WeightedEdge { + if g.HasEdgeFromTo(uid, vid) { + // xid and yid are not greater than maximum int by this point. + return WeightedEdge{F: g.Node(uid), T: g.Node(vid), W: g.mat.At(int(uid), int(vid))} + } + return nil +} + +// WeightedEdges returns all the edges in the graph. +func (g *DirectedMatrix) WeightedEdges() graph.WeightedEdges { + var edges []graph.WeightedEdge + 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, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w}) + } + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedWeightedEdges(edges) +} + +func (g *DirectedMatrix) has(id int64) bool { + r, _ := g.mat.Dims() + return 0 <= id && id < int64(r) } diff --git a/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go b/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go index 5ae9262682d..f51debb4fcc 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/dense_undirected_matrix.go @@ -9,9 +9,19 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/ordered" + "gonum.org/v1/gonum/graph/iterator" "gonum.org/v1/gonum/mat" ) +var ( + um *UndirectedMatrix + + _ graph.Graph = um + _ graph.Undirected = um + _ edgeSetter = um + _ weightedEdgeSetter = um +) + // 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 @@ -63,44 +73,19 @@ func NewUndirectedMatrixFrom(nodes []graph.Node, init, self, absent float64) *Un return g } -// Node returns the node in the graph with the given ID. -func (g *UndirectedMatrix) Node(id int64) graph.Node { - if !g.has(id) { - return nil - } - if g.nodes == nil { - return Node(id) - } - return g.nodes[id] +// 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(uid, vid int64) graph.Edge { + return g.WeightedEdgeBetween(uid, vid) } -// Has returns whether the node exists within the graph. -func (g *UndirectedMatrix) Has(id int64) bool { - return g.has(id) -} - -func (g *UndirectedMatrix) has(id int64) bool { - r := g.mat.Symmetric() - return 0 <= id && id < int64(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 +// EdgeBetween returns the edge between nodes x and y. +func (g *UndirectedMatrix) EdgeBetween(uid, vid int64) graph.Edge { + return g.WeightedEdgeBetween(uid, vid) } // Edges returns all the edges in the graph. -func (g *UndirectedMatrix) Edges() []graph.Edge { +func (g *UndirectedMatrix) Edges() graph.Edges { var edges []graph.Edge r, _ := g.mat.Dims() for i := 0; i < r; i++ { @@ -110,15 +95,18 @@ func (g *UndirectedMatrix) Edges() []graph.Edge { } } } - return edges + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedEdges(edges) } // From returns all nodes in g that can be reached directly from n. -func (g *UndirectedMatrix) From(id int64) []graph.Node { +func (g *UndirectedMatrix) From(id int64) graph.Nodes { if !g.has(id) { - return nil + return graph.Empty } - var neighbors []graph.Node + var nodes []graph.Node r := g.mat.Symmetric() for i := 0; i < r; i++ { if int64(i) == id { @@ -126,10 +114,13 @@ func (g *UndirectedMatrix) From(id int64) []graph.Node { } // id is not greater than maximum int by this point. if !isSame(g.mat.At(int(id), i), g.absent) { - neighbors = append(neighbors, g.Node(int64(i))) + nodes = append(nodes, g.Node(int64(i))) } } - return neighbors + if len(nodes) == 0 { + return graph.Empty + } + return iterator.NewOrderedNodes(nodes) } // HasEdgeBetween returns whether an edge exists between nodes x and y. @@ -144,73 +135,35 @@ func (g *UndirectedMatrix) HasEdgeBetween(uid, vid int64) bool { return uid != vid && !isSame(g.mat.At(int(uid), int(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(uid, vid int64) graph.Edge { - return g.WeightedEdgeBetween(uid, vid) +// Matrix returns the mat.Matrix representation of the graph. +func (g *UndirectedMatrix) Matrix() mat.Matrix { + // Prevent alteration of dimensions of the returned matrix. + m := *g.mat + return &m } -// WeightedEdge returns the weighted 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) WeightedEdge(uid, vid int64) graph.WeightedEdge { - return g.WeightedEdgeBetween(uid, vid) -} - -// EdgeBetween returns the edge between nodes x and y. -func (g *UndirectedMatrix) EdgeBetween(uid, vid int64) graph.Edge { - return g.WeightedEdgeBetween(uid, vid) -} - -// WeightedEdgeBetween returns the weighted edge between nodes x and y. -func (g *UndirectedMatrix) WeightedEdgeBetween(uid, vid int64) graph.WeightedEdge { - if g.HasEdgeBetween(uid, vid) { - // uid and vid are not greater than maximum int by this point. - return WeightedEdge{F: g.Node(uid), T: g.Node(vid), W: g.mat.At(int(uid), int(vid))} +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g *UndirectedMatrix) Node(id int64) graph.Node { + if !g.has(id) { + return nil } - return nil + if g.nodes == nil { + return Node(id) + } + return g.nodes[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 *UndirectedMatrix) Weight(xid, yid int64) (w float64, ok bool) { - if xid == yid { - return g.self, true +// Nodes returns all the nodes in the graph. +func (g *UndirectedMatrix) Nodes() graph.Nodes { + if g.nodes != nil { + nodes := make([]graph.Node, len(g.nodes)) + copy(nodes, g.nodes) + return iterator.NewOrderedNodes(nodes) } - if g.has(xid) && g.has(yid) { - // xid and yid are not greater than maximum int by this point. - return g.mat.At(int(xid), int(yid)), true - } - return g.absent, false -} - -// SetEdge sets e, an edge from one node to another with unit weight. 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) { - g.setWeightedEdge(e, 1) -} - -// SetWeightedEdge 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, SetWeightedEdge panics. -func (g *UndirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) { - g.setWeightedEdge(e, e.Weight()) -} - -func (g *UndirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) { - fid := e.From().ID() - tid := e.To().ID() - if fid == tid { - panic("simple: set illegal edge") - } - if int64(int(fid)) != fid { - panic("simple: unavailable from node ID for dense graph") - } - if int64(int(tid)) != tid { - panic("simple: unavailable to node ID for dense graph") - } - // fid and tid are not greater than maximum int by this point. - g.mat.SetSym(int(fid), int(tid), weight) + r := g.mat.Symmetric() + // Matrix graphs must have at least one node. + return iterator.NewImplicitNodes(0, r, newSimpleNode) } // RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal @@ -226,28 +179,90 @@ func (g *UndirectedMatrix) RemoveEdge(fid, tid int64) { g.mat.SetSym(int(fid), int(tid), g.absent) } -// Degree returns the degree of n in g. -func (g *UndirectedMatrix) Degree(id int64) int { - if !g.has(id) { - return 0 - } - var deg int - r := g.mat.Symmetric() - for i := 0; i < r; i++ { - if int64(i) == id { - continue - } - // id is not greater than maximum int by this point. - if !isSame(g.mat.At(int(id), i), g.absent) { - deg++ - } - } - return deg +// SetEdge sets e, an edge from one node to another with unit weight. If the ends of the edge are +// not in g or the edge is a self loop, SetEdge panics. SetEdge will store the nodes of +// e in the graph if it was initialized with NewUndirectedMatrixFrom. +func (g *UndirectedMatrix) SetEdge(e graph.Edge) { + g.setWeightedEdge(e, 1) } -// Matrix returns the mat.Matrix representation of the graph. -func (g *UndirectedMatrix) Matrix() mat.Matrix { - // Prevent alteration of dimensions of the returned matrix. - m := *g.mat - return &m +// SetWeightedEdge 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, SetWeightedEdge panics. SetWeightedEdge will store the nodes of +// e in the graph if it was initialized with NewUndirectedMatrixFrom. +func (g *UndirectedMatrix) SetWeightedEdge(e graph.WeightedEdge) { + g.setWeightedEdge(e, e.Weight()) +} + +func (g *UndirectedMatrix) setWeightedEdge(e graph.Edge, weight float64) { + from := e.From() + fid := from.ID() + to := e.To() + tid := to.ID() + if fid == tid { + panic("simple: set illegal edge") + } + if int64(int(fid)) != fid { + panic("simple: unavailable from node ID for dense graph") + } + if int64(int(tid)) != tid { + panic("simple: unavailable to node ID for dense graph") + } + if g.nodes != nil { + g.nodes[fid] = from + g.nodes[tid] = to + } + // fid and tid are not greater than maximum int by this point. + g.mat.SetSym(int(fid), int(tid), weight) +} + +// 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(xid, yid int64) (w float64, ok bool) { + if xid == yid { + return g.self, true + } + if g.HasEdgeBetween(xid, yid) { + // xid and yid are not greater than maximum int by this point. + return g.mat.At(int(xid), int(yid)), true + } + return g.absent, false +} + +// WeightedEdge returns the weighted 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) WeightedEdge(uid, vid int64) graph.WeightedEdge { + return g.WeightedEdgeBetween(uid, vid) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. +func (g *UndirectedMatrix) WeightedEdgeBetween(uid, vid int64) graph.WeightedEdge { + if g.HasEdgeBetween(uid, vid) { + // uid and vid are not greater than maximum int by this point. + return WeightedEdge{F: g.Node(uid), T: g.Node(vid), W: g.mat.At(int(uid), int(vid))} + } + return nil +} + +// WeightedEdges returns all the edges in the graph. +func (g *UndirectedMatrix) WeightedEdges() graph.WeightedEdges { + var edges []graph.WeightedEdge + 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, WeightedEdge{F: g.Node(int64(i)), T: g.Node(int64(j)), W: w}) + } + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedWeightedEdges(edges) +} + +func (g *UndirectedMatrix) has(id int64) bool { + r := g.mat.Symmetric() + return 0 <= id && id < int64(r) } diff --git a/vendor/gonum.org/v1/gonum/graph/simple/directed.go b/vendor/gonum.org/v1/gonum/graph/simple/directed.go index 6be172f1568..f19efbd0a2c 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/directed.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/directed.go @@ -9,6 +9,18 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/uid" + "gonum.org/v1/gonum/graph/iterator" +) + +var ( + dg *DirectedGraph + + _ graph.Graph = dg + _ graph.Directed = dg + _ graph.NodeAdder = dg + _ graph.NodeRemover = dg + _ graph.EdgeAdder = dg + _ graph.EdgeRemover = dg ) // DirectedGraph implements a generalized directed graph. @@ -31,6 +43,82 @@ func NewDirectedGraph() *DirectedGraph { } } +// 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[int64]graph.Edge) + g.to[n.ID()] = make(map[int64]graph.Edge) + g.nodeIDs.Use(n.ID()) +} + +// 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(uid, vid int64) graph.Edge { + edge, ok := g.from[uid][vid] + if !ok { + return nil + } + return edge +} + +// Edges returns all the edges in the graph. +func (g *DirectedGraph) Edges() graph.Edges { + var edges []graph.Edge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedEdges(edges) +} + +// From returns all nodes in g that can be reached directly from n. +func (g *DirectedGraph) From(id int64) graph.Nodes { + if _, ok := g.from[id]; !ok { + return graph.Empty + } + + from := make([]graph.Node, len(g.from[id])) + i := 0 + for vid := range g.from[id] { + from[i] = g.nodes[vid] + i++ + } + if len(from) == 0 { + return graph.Empty + } + return iterator.NewOrderedNodes(from) +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *DirectedGraph) HasEdgeBetween(xid, yid int64) bool { + if _, ok := g.from[xid][yid]; ok { + return true + } + _, ok := g.from[yid][xid] + return ok +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *DirectedGraph) HasEdgeFromTo(uid, vid int64) bool { + if _, ok := g.from[uid][vid]; !ok { + return false + } + return true +} + +// NewEdge returns a new Edge from the source to the destination node. +func (g *DirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &Edge{F: from, T: to} +} + // NewNode returns a new unique Node to be added to g. The Node's ID does // not become valid in g until the Node is added to g. func (g *DirectedGraph) NewNode() graph.Node { @@ -43,15 +131,38 @@ func (g *DirectedGraph) NewNode() graph.Node { return Node(g.nodeIDs.NewID()) } -// 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())) +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g *DirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Nodes returns all the nodes in the graph. +func (g *DirectedGraph) Nodes() graph.Nodes { + if len(g.nodes) == 0 { + return graph.Empty } - g.nodes[n.ID()] = n - g.from[n.ID()] = make(map[int64]graph.Edge) - g.to[n.ID()] = make(map[int64]graph.Edge) - g.nodeIDs.Use(n.ID()) + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + return iterator.NewOrderedNodes(nodes) +} + +// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal +// nodes. If the edge does not exist it is a no-op. +func (g *DirectedGraph) RemoveEdge(fid, tid int64) { + if _, ok := g.nodes[fid]; !ok { + return + } + if _, ok := g.nodes[tid]; !ok { + return + } + + delete(g.from[fid], tid) + delete(g.to[tid], fid) } // RemoveNode removes the node with the given ID from the graph, as well as any edges attached @@ -75,12 +186,8 @@ func (g *DirectedGraph) RemoveNode(id int64) { g.nodeIDs.Release(id) } -// NewEdge returns a new Edge from the source to the destination node. -func (g *DirectedGraph) NewEdge(from, to graph.Node) graph.Edge { - return &Edge{F: from, T: to} -} - -// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added. +// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added +// and are set to the nodes of the edge otherwise. // It will panic if the IDs of the e.From and e.To are equal. func (g *DirectedGraph) SetEdge(e graph.Edge) { var ( @@ -94,86 +201,25 @@ func (g *DirectedGraph) SetEdge(e graph.Edge) { panic("simple: adding self edge") } - if !g.Has(fid) { + if _, ok := g.nodes[fid]; !ok { g.AddNode(from) + } else { + g.nodes[fid] = from } - if !g.Has(tid) { + if _, ok := g.nodes[tid]; !ok { g.AddNode(to) + } else { + g.nodes[tid] = to } g.from[fid][tid] = e g.to[tid][fid] = e } -// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal -// nodes. If the edge does not exist it is a no-op. -func (g *DirectedGraph) RemoveEdge(fid, tid int64) { - if _, ok := g.nodes[fid]; !ok { - return - } - if _, ok := g.nodes[tid]; !ok { - return - } - - delete(g.from[fid], tid) - delete(g.to[tid], fid) -} - -// Node returns the node in the graph with the given ID. -func (g *DirectedGraph) Node(id int64) graph.Node { - return g.nodes[id] -} - -// Has returns whether the node exists within the graph. -func (g *DirectedGraph) Has(id int64) bool { - _, ok := g.nodes[id] - return ok -} - -// Nodes returns all the nodes in the graph. -func (g *DirectedGraph) Nodes() []graph.Node { - if len(g.nodes) == 0 { - return nil - } - 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 *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(id int64) []graph.Node { - if _, ok := g.from[id]; !ok { - return nil - } - - from := make([]graph.Node, len(g.from[id])) - i := 0 - for vid := range g.from[id] { - from[i] = g.nodes[vid] - i++ - } - return from -} - // To returns all nodes in g that can reach directly to n. -func (g *DirectedGraph) To(id int64) []graph.Node { +func (g *DirectedGraph) To(id int64) graph.Nodes { if _, ok := g.from[id]; !ok { - return nil + return graph.Empty } to := make([]graph.Node, len(g.to[id])) @@ -182,41 +228,8 @@ func (g *DirectedGraph) To(id int64) []graph.Node { to[i] = g.nodes[uid] i++ } - return to -} - -// HasEdgeBetween returns whether an edge exists between nodes x and y without -// considering direction. -func (g *DirectedGraph) HasEdgeBetween(xid, yid int64) bool { - if _, ok := g.from[xid][yid]; ok { - return true + if len(to) == 0 { + return graph.Empty } - _, 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(uid, vid int64) graph.Edge { - edge, ok := g.from[uid][vid] - if !ok { - return nil - } - return edge -} - -// HasEdgeFromTo returns whether an edge exists in the graph from u to v. -func (g *DirectedGraph) HasEdgeFromTo(uid, vid int64) bool { - if _, ok := g.from[uid][vid]; !ok { - return false - } - return true -} - -// Degree returns the in+out degree of n in g. -func (g *DirectedGraph) Degree(id int64) int { - if _, ok := g.nodes[id]; !ok { - return 0 - } - return len(g.from[id]) + len(g.to[id]) + return iterator.NewOrderedNodes(to) } diff --git a/vendor/gonum.org/v1/gonum/graph/simple/doc.go b/vendor/gonum.org/v1/gonum/graph/simple/doc.go index a26818bdc0e..dc3f24c54fd 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/doc.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/doc.go @@ -4,4 +4,6 @@ // Package simple provides a suite of simple graph implementations satisfying // the gonum/graph interfaces. +// +// All types in simple return the graph.Empty value for empty iterators. package simple // import "gonum.org/v1/gonum/graph/simple" diff --git a/vendor/gonum.org/v1/gonum/graph/simple/simple.go b/vendor/gonum.org/v1/gonum/graph/simple/simple.go index a9ddfd5fa3f..3b457658778 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/simple.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/simple.go @@ -18,6 +18,10 @@ func (n Node) ID() int64 { return int64(n) } +func newSimpleNode(id int) graph.Node { + return Node(id) +} + // Edge is a simple graph edge. type Edge struct { F, T graph.Node @@ -29,6 +33,10 @@ 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 } +// ReversedLine returns a new Edge with the F and T fields +// swapped. +func (e Edge) ReversedEdge() graph.Edge { return Edge{F: e.T, T: e.F} } + // WeightedEdge is a simple weighted graph edge. type WeightedEdge struct { F, T graph.Node @@ -41,6 +49,11 @@ func (e WeightedEdge) From() graph.Node { return e.F } // To returns the to-node of the edge. func (e WeightedEdge) To() graph.Node { return e.T } +// ReversedLine returns a new Edge with the F and T fields +// swapped. The weight of the new Edge is the same as +// the weight of the receiver. +func (e WeightedEdge) ReversedEdge() graph.Edge { return WeightedEdge{F: e.T, T: e.F, W: e.W} } + // Weight returns the weight of the edge. func (e WeightedEdge) Weight() float64 { return e.W } @@ -49,3 +62,11 @@ func (e WeightedEdge) Weight() float64 { return e.W } func isSame(a, b float64) bool { return a == b || (math.IsNaN(a) && math.IsNaN(b)) } + +type edgeSetter interface { + SetEdge(e graph.Edge) +} + +type weightedEdgeSetter interface { + SetWeightedEdge(e graph.WeightedEdge) +} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/undirected.go b/vendor/gonum.org/v1/gonum/graph/simple/undirected.go index b13d6d4861e..841a8e380c5 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/undirected.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/undirected.go @@ -9,6 +9,18 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/uid" + "gonum.org/v1/gonum/graph/iterator" +) + +var ( + ug *UndirectedGraph + + _ graph.Graph = ug + _ graph.Undirected = ug + _ graph.NodeAdder = ug + _ graph.NodeRemover = ug + _ graph.EdgeAdder = ug + _ graph.EdgeRemover = ug ) // UndirectedGraph implements a generalized undirected graph. @@ -29,6 +41,88 @@ func NewUndirectedGraph() *UndirectedGraph { } } +// 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[int64]graph.Edge) + g.nodeIDs.Use(n.ID()) +} + +// 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(uid, vid int64) graph.Edge { + return g.EdgeBetween(uid, vid) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *UndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge { + edge, ok := g.edges[xid][yid] + if !ok { + return nil + } + if edge.From().ID() == xid { + return edge + } + return edge.ReversedEdge() +} + +// Edges returns all the edges in the graph. +func (g *UndirectedGraph) Edges() graph.Edges { + if len(g.edges) == 0 { + return graph.Empty + } + var edges []graph.Edge + seen := make(map[[2]int64]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int64{uid, vid}]; ok { + continue + } + seen[[2]int64{uid, vid}] = struct{}{} + seen[[2]int64{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedEdges(edges) +} + +// From returns all nodes in g that can be reached directly from n. +func (g *UndirectedGraph) From(id int64) graph.Nodes { + if _, ok := g.nodes[id]; !ok { + return graph.Empty + } + + nodes := make([]graph.Node, len(g.edges[id])) + i := 0 + for from := range g.edges[id] { + nodes[i] = g.nodes[from] + i++ + } + if len(nodes) == 0 { + return graph.Empty + } + return iterator.NewOrderedNodes(nodes) +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *UndirectedGraph) HasEdgeBetween(xid, yid int64) bool { + _, ok := g.edges[xid][yid] + return ok +} + +// NewEdge returns a new Edge from the source to the destination node. +func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge { + return &Edge{F: from, T: to} +} + // NewNode returns a new unique Node to be added to g. The Node's ID does // not become valid in g until the Node is added to g. func (g *UndirectedGraph) NewNode() graph.Node { @@ -41,14 +135,38 @@ func (g *UndirectedGraph) NewNode() graph.Node { return Node(g.nodeIDs.NewID()) } -// 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())) +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g *UndirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Nodes returns all the nodes in the graph. +func (g *UndirectedGraph) Nodes() graph.Nodes { + if len(g.nodes) == 0 { + return graph.Empty } - g.nodes[n.ID()] = n - g.edges[n.ID()] = make(map[int64]graph.Edge) - g.nodeIDs.Use(n.ID()) + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + return iterator.NewOrderedNodes(nodes) +} + +// RemoveEdge removes the edge with the given end IDs from the graph, leaving the terminal nodes. +// If the edge does not exist it is a no-op. +func (g *UndirectedGraph) RemoveEdge(fid, tid int64) { + if _, ok := g.nodes[fid]; !ok { + return + } + if _, ok := g.nodes[tid]; !ok { + return + } + + delete(g.edges[fid], tid) + delete(g.edges[tid], fid) } // RemoveNode removes the node with the given ID from the graph, as well as any edges attached @@ -67,12 +185,8 @@ func (g *UndirectedGraph) RemoveNode(id int64) { g.nodeIDs.Release(id) } -// NewEdge returns a new Edge from the source to the destination node. -func (g *UndirectedGraph) NewEdge(from, to graph.Node) graph.Edge { - return &Edge{F: from, T: to} -} - -// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added. +// SetEdge adds e, an edge from one node to another. If the nodes do not exist, they are added +// and are set to the nodes of the edge otherwise. // It will panic if the IDs of the e.From and e.To are equal. func (g *UndirectedGraph) SetEdge(e graph.Edge) { var ( @@ -86,118 +200,17 @@ func (g *UndirectedGraph) SetEdge(e graph.Edge) { panic("simple: adding self edge") } - if !g.Has(fid) { + if _, ok := g.nodes[fid]; !ok { g.AddNode(from) + } else { + g.nodes[fid] = from } - if !g.Has(tid) { + if _, ok := g.nodes[tid]; !ok { g.AddNode(to) + } else { + g.nodes[tid] = to } g.edges[fid][tid] = e g.edges[tid][fid] = e } - -// RemoveEdge removes the edge with the given end IDs from the graph, leaving the terminal nodes. -// If the edge does not exist it is a no-op. -func (g *UndirectedGraph) RemoveEdge(fid, tid int64) { - if _, ok := g.nodes[fid]; !ok { - return - } - if _, ok := g.nodes[tid]; !ok { - return - } - - delete(g.edges[fid], tid) - delete(g.edges[tid], fid) -} - -// Node returns the node in the graph with the given ID. -func (g *UndirectedGraph) Node(id int64) graph.Node { - return g.nodes[id] -} - -// Has returns whether the node exists within the graph. -func (g *UndirectedGraph) Has(id int64) bool { - _, ok := g.nodes[id] - return ok -} - -// Nodes returns all the nodes in the graph. -func (g *UndirectedGraph) Nodes() []graph.Node { - if len(g.nodes) == 0 { - return nil - } - 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 { - if len(g.edges) == 0 { - return nil - } - var edges []graph.Edge - seen := make(map[[2]int64]struct{}) - for _, u := range g.edges { - for _, e := range u { - uid := e.From().ID() - vid := e.To().ID() - if _, ok := seen[[2]int64{uid, vid}]; ok { - continue - } - seen[[2]int64{uid, vid}] = struct{}{} - seen[[2]int64{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(id int64) []graph.Node { - if !g.Has(id) { - return nil - } - - nodes := make([]graph.Node, len(g.edges[id])) - i := 0 - for from := range g.edges[id] { - nodes[i] = g.nodes[from] - i++ - } - return nodes -} - -// HasEdgeBetween returns whether an edge exists between nodes x and y. -func (g *UndirectedGraph) HasEdgeBetween(xid, yid int64) bool { - _, ok := g.edges[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 *UndirectedGraph) Edge(uid, vid int64) graph.Edge { - return g.EdgeBetween(uid, vid) -} - -// EdgeBetween returns the edge between nodes x and y. -func (g *UndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge { - edge, ok := g.edges[xid][yid] - if !ok { - return nil - } - return edge -} - -// Degree returns the degree of n in g. -func (g *UndirectedGraph) Degree(id int64) int { - if _, ok := g.nodes[id]; !ok { - return 0 - } - return len(g.edges[id]) -} diff --git a/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go b/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go index 591f9a51b31..92bd2842fdf 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/weighted_directed.go @@ -9,6 +9,20 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/uid" + "gonum.org/v1/gonum/graph/iterator" +) + +var ( + wdg *WeightedDirectedGraph + + _ graph.Graph = wdg + _ graph.Weighted = wdg + _ graph.Directed = wdg + _ graph.WeightedDirected = wdg + _ graph.NodeAdder = wdg + _ graph.NodeRemover = wdg + _ graph.WeightedEdgeAdder = wdg + _ graph.EdgeRemover = wdg ) // WeightedDirectedGraph implements a generalized weighted directed graph. @@ -37,6 +51,73 @@ func NewWeightedDirectedGraph(self, absent float64) *WeightedDirectedGraph { } } +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *WeightedDirectedGraph) 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[int64]graph.WeightedEdge) + g.to[n.ID()] = make(map[int64]graph.WeightedEdge) + g.nodeIDs.Use(n.ID()) +} + +// 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 *WeightedDirectedGraph) Edge(uid, vid int64) graph.Edge { + return g.WeightedEdge(uid, vid) +} + +// Edges returns all the edges in the graph. +func (g *WeightedDirectedGraph) Edges() graph.Edges { + var edges []graph.Edge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedEdges(edges) +} + +// From returns all nodes in g that can be reached directly from n. +func (g *WeightedDirectedGraph) From(id int64) graph.Nodes { + if _, ok := g.from[id]; !ok { + return graph.Empty + } + + from := make([]graph.Node, len(g.from[id])) + i := 0 + for vid := range g.from[id] { + from[i] = g.nodes[vid] + i++ + } + if len(from) == 0 { + return graph.Empty + } + return iterator.NewOrderedNodes(from) +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y without +// considering direction. +func (g *WeightedDirectedGraph) HasEdgeBetween(xid, yid int64) bool { + if _, ok := g.from[xid][yid]; ok { + return true + } + _, ok := g.from[yid][xid] + return ok +} + +// HasEdgeFromTo returns whether an edge exists in the graph from u to v. +func (g *WeightedDirectedGraph) HasEdgeFromTo(uid, vid int64) bool { + if _, ok := g.from[uid][vid]; !ok { + return false + } + return true +} + // NewNode returns a new unique Node to be added to g. The Node's ID does // not become valid in g until the Node is added to g. func (g *WeightedDirectedGraph) NewNode() graph.Node { @@ -49,15 +130,43 @@ func (g *WeightedDirectedGraph) NewNode() graph.Node { return Node(g.nodeIDs.NewID()) } -// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. -func (g *WeightedDirectedGraph) AddNode(n graph.Node) { - if _, exists := g.nodes[n.ID()]; exists { - panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) +// NewWeightedEdge returns a new weighted edge from the source to the destination node. +func (g *WeightedDirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge { + return &WeightedEdge{F: from, T: to, W: weight} +} + +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g *WeightedDirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Nodes returns all the nodes in the graph. +func (g *WeightedDirectedGraph) Nodes() graph.Nodes { + if len(g.from) == 0 { + return graph.Empty } - g.nodes[n.ID()] = n - g.from[n.ID()] = make(map[int64]graph.WeightedEdge) - g.to[n.ID()] = make(map[int64]graph.WeightedEdge) - g.nodeIDs.Use(n.ID()) + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + return iterator.NewOrderedNodes(nodes) +} + +// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal +// nodes. If the edge does not exist it is a no-op. +func (g *WeightedDirectedGraph) RemoveEdge(fid, tid int64) { + if _, ok := g.nodes[fid]; !ok { + return + } + if _, ok := g.nodes[tid]; !ok { + return + } + + delete(g.from[fid], tid) + delete(g.to[tid], fid) } // RemoveNode removes the node with the given ID from the graph, as well as any edges attached @@ -81,12 +190,8 @@ func (g *WeightedDirectedGraph) RemoveNode(id int64) { g.nodeIDs.Release(id) } -// NewWeightedEdge returns a new weighted edge from the source to the destination node. -func (g *WeightedDirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge { - return &WeightedEdge{F: from, T: to, W: weight} -} - -// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added. +// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added +// and are set to the nodes of the edge otherwise. // It will panic if the IDs of the e.From and e.To are equal. func (g *WeightedDirectedGraph) SetWeightedEdge(e graph.WeightedEdge) { var ( @@ -100,97 +205,25 @@ func (g *WeightedDirectedGraph) SetWeightedEdge(e graph.WeightedEdge) { panic("simple: adding self edge") } - if !g.Has(fid) { + if _, ok := g.nodes[fid]; !ok { g.AddNode(from) + } else { + g.nodes[fid] = from } - if !g.Has(tid) { + if _, ok := g.nodes[tid]; !ok { g.AddNode(to) + } else { + g.nodes[tid] = to } g.from[fid][tid] = e g.to[tid][fid] = e } -// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal -// nodes. If the edge does not exist it is a no-op. -func (g *WeightedDirectedGraph) RemoveEdge(fid, tid int64) { - if _, ok := g.nodes[fid]; !ok { - return - } - if _, ok := g.nodes[tid]; !ok { - return - } - - delete(g.from[fid], tid) - delete(g.to[tid], fid) -} - -// Node returns the node in the graph with the given ID. -func (g *WeightedDirectedGraph) Node(id int64) graph.Node { - return g.nodes[id] -} - -// Has returns whether the node exists within the graph. -func (g *WeightedDirectedGraph) Has(id int64) bool { - _, ok := g.nodes[id] - return ok -} - -// Nodes returns all the nodes in the graph. -func (g *WeightedDirectedGraph) Nodes() []graph.Node { - if len(g.from) == 0 { - return nil - } - 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 *WeightedDirectedGraph) 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 -} - -// WeightedEdges returns all the weighted edges in the graph. -func (g *WeightedDirectedGraph) WeightedEdges() []graph.WeightedEdge { - var edges []graph.WeightedEdge - 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 *WeightedDirectedGraph) From(id int64) []graph.Node { - if _, ok := g.from[id]; !ok { - return nil - } - - from := make([]graph.Node, len(g.from[id])) - i := 0 - for vid := range g.from[id] { - from[i] = g.nodes[vid] - i++ - } - return from -} - // To returns all nodes in g that can reach directly to n. -func (g *WeightedDirectedGraph) To(id int64) []graph.Node { +func (g *WeightedDirectedGraph) To(id int64) graph.Nodes { if _, ok := g.from[id]; !ok { - return nil + return graph.Empty } to := make([]graph.Node, len(g.to[id])) @@ -199,41 +232,10 @@ func (g *WeightedDirectedGraph) To(id int64) []graph.Node { to[i] = g.nodes[uid] i++ } - return to -} - -// HasEdgeBetween returns whether an edge exists between nodes x and y without -// considering direction. -func (g *WeightedDirectedGraph) HasEdgeBetween(xid, yid int64) bool { - if _, ok := g.from[xid][yid]; ok { - return true + if len(to) == 0 { + return graph.Empty } - _, 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 *WeightedDirectedGraph) Edge(uid, vid int64) graph.Edge { - return g.WeightedEdge(uid, vid) -} - -// WeightedEdge returns the weighted 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 *WeightedDirectedGraph) WeightedEdge(uid, vid int64) graph.WeightedEdge { - edge, ok := g.from[uid][vid] - if !ok { - return nil - } - return edge -} - -// HasEdgeFromTo returns whether an edge exists in the graph from u to v. -func (g *WeightedDirectedGraph) HasEdgeFromTo(uid, vid int64) bool { - if _, ok := g.from[uid][vid]; !ok { - return false - } - return true + return iterator.NewOrderedNodes(to) } // Weight returns the weight for the edge between x and y if Edge(x, y) returns a non-nil Edge. @@ -252,10 +254,26 @@ func (g *WeightedDirectedGraph) Weight(xid, yid int64) (w float64, ok bool) { return g.absent, false } -// Degree returns the in+out degree of n in g. -func (g *WeightedDirectedGraph) Degree(id int64) int { - if _, ok := g.nodes[id]; !ok { - return 0 +// WeightedEdge returns the weighted 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 *WeightedDirectedGraph) WeightedEdge(uid, vid int64) graph.WeightedEdge { + edge, ok := g.from[uid][vid] + if !ok { + return nil } - return len(g.from[id]) + len(g.to[id]) + return edge +} + +// WeightedEdges returns all the weighted edges in the graph. +func (g *WeightedDirectedGraph) WeightedEdges() graph.WeightedEdges { + var edges []graph.WeightedEdge + for _, u := range g.nodes { + for _, e := range g.from[u.ID()] { + edges = append(edges, e) + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedWeightedEdges(edges) } diff --git a/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go b/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go index 525de1ec59c..5932576832e 100644 --- a/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go +++ b/vendor/gonum.org/v1/gonum/graph/simple/weighted_undirected.go @@ -9,6 +9,20 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/uid" + "gonum.org/v1/gonum/graph/iterator" +) + +var ( + wug *WeightedUndirectedGraph + + _ graph.Graph = wug + _ graph.Weighted = wug + _ graph.Undirected = wug + _ graph.WeightedUndirected = wug + _ graph.NodeAdder = wug + _ graph.NodeRemover = wug + _ graph.WeightedEdgeAdder = wug + _ graph.EdgeRemover = wug ) // WeightedUndirectedGraph implements a generalized weighted undirected graph. @@ -35,6 +49,76 @@ func NewWeightedUndirectedGraph(self, absent float64) *WeightedUndirectedGraph { } } +// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. +func (g *WeightedUndirectedGraph) 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[int64]graph.WeightedEdge) + g.nodeIDs.Use(n.ID()) +} + +// 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 *WeightedUndirectedGraph) Edge(uid, vid int64) graph.Edge { + return g.WeightedEdgeBetween(uid, vid) +} + +// EdgeBetween returns the edge between nodes x and y. +func (g *WeightedUndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge { + return g.WeightedEdgeBetween(xid, yid) +} + +// Edges returns all the edges in the graph. +func (g *WeightedUndirectedGraph) Edges() graph.Edges { + if len(g.edges) == 0 { + return graph.Empty + } + var edges []graph.Edge + seen := make(map[[2]int64]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int64{uid, vid}]; ok { + continue + } + seen[[2]int64{uid, vid}] = struct{}{} + seen[[2]int64{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedEdges(edges) +} + +// From returns all nodes in g that can be reached directly from n. +func (g *WeightedUndirectedGraph) From(id int64) graph.Nodes { + if _, ok := g.nodes[id]; !ok { + return graph.Empty + } + + nodes := make([]graph.Node, len(g.edges[id])) + i := 0 + for from := range g.edges[id] { + nodes[i] = g.nodes[from] + i++ + } + if len(nodes) == 0 { + return graph.Empty + } + return iterator.NewOrderedNodes(nodes) +} + +// HasEdgeBetween returns whether an edge exists between nodes x and y. +func (g *WeightedUndirectedGraph) HasEdgeBetween(xid, yid int64) bool { + _, ok := g.edges[xid][yid] + return ok +} + // NewNode returns a new unique Node to be added to g. The Node's ID does // not become valid in g until the Node is added to g. func (g *WeightedUndirectedGraph) NewNode() graph.Node { @@ -47,14 +131,43 @@ func (g *WeightedUndirectedGraph) NewNode() graph.Node { return Node(g.nodeIDs.NewID()) } -// AddNode adds n to the graph. It panics if the added node ID matches an existing node ID. -func (g *WeightedUndirectedGraph) AddNode(n graph.Node) { - if _, exists := g.nodes[n.ID()]; exists { - panic(fmt.Sprintf("simple: node ID collision: %d", n.ID())) +// NewWeightedEdge returns a new weighted edge from the source to the destination node. +func (g *WeightedUndirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge { + return &WeightedEdge{F: from, T: to, W: weight} +} + +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g *WeightedUndirectedGraph) Node(id int64) graph.Node { + return g.nodes[id] +} + +// Nodes returns all the nodes in the graph. +func (g *WeightedUndirectedGraph) Nodes() graph.Nodes { + if len(g.nodes) == 0 { + return graph.Empty } - g.nodes[n.ID()] = n - g.edges[n.ID()] = make(map[int64]graph.WeightedEdge) - g.nodeIDs.Use(n.ID()) + nodes := make([]graph.Node, len(g.nodes)) + i := 0 + for _, n := range g.nodes { + nodes[i] = n + i++ + } + return iterator.NewOrderedNodes(nodes) +} + +// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal +// nodes. If the edge does not exist it is a no-op. +func (g *WeightedUndirectedGraph) RemoveEdge(fid, tid int64) { + if _, ok := g.nodes[fid]; !ok { + return + } + if _, ok := g.nodes[tid]; !ok { + return + } + + delete(g.edges[fid], tid) + delete(g.edges[tid], fid) } // RemoveNode removes the node with the given ID from the graph, as well as any edges attached @@ -73,12 +186,8 @@ func (g *WeightedUndirectedGraph) RemoveNode(id int64) { g.nodeIDs.Release(id) } -// NewWeightedEdge returns a new weighted edge from the source to the destination node. -func (g *WeightedUndirectedGraph) NewWeightedEdge(from, to graph.Node, weight float64) graph.WeightedEdge { - return &WeightedEdge{F: from, T: to, W: weight} -} - -// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added. +// SetWeightedEdge adds a weighted edge from one node to another. If the nodes do not exist, they are added +// and are set to the nodes of the edge otherwise. // It will panic if the IDs of the e.From and e.To are equal. func (g *WeightedUndirectedGraph) SetWeightedEdge(e graph.WeightedEdge) { var ( @@ -92,144 +201,21 @@ func (g *WeightedUndirectedGraph) SetWeightedEdge(e graph.WeightedEdge) { panic("simple: adding self edge") } - if !g.Has(fid) { + if _, ok := g.nodes[fid]; !ok { g.AddNode(from) + } else { + g.nodes[fid] = from } - if !g.Has(tid) { + if _, ok := g.nodes[tid]; !ok { g.AddNode(to) + } else { + g.nodes[tid] = to } g.edges[fid][tid] = e g.edges[tid][fid] = e } -// RemoveEdge removes the edge with the given end point IDs from the graph, leaving the terminal -// nodes. If the edge does not exist it is a no-op. -func (g *WeightedUndirectedGraph) RemoveEdge(fid, tid int64) { - if _, ok := g.nodes[fid]; !ok { - return - } - if _, ok := g.nodes[tid]; !ok { - return - } - - delete(g.edges[fid], tid) - delete(g.edges[tid], fid) -} - -// Node returns the node in the graph with the given ID. -func (g *WeightedUndirectedGraph) Node(id int64) graph.Node { - return g.nodes[id] -} - -// Has returns whether the node exists within the graph. -func (g *WeightedUndirectedGraph) Has(id int64) bool { - _, ok := g.nodes[id] - return ok -} - -// Nodes returns all the nodes in the graph. -func (g *WeightedUndirectedGraph) Nodes() []graph.Node { - if len(g.nodes) == 0 { - return nil - } - 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 *WeightedUndirectedGraph) Edges() []graph.Edge { - if len(g.edges) == 0 { - return nil - } - var edges []graph.Edge - seen := make(map[[2]int64]struct{}) - for _, u := range g.edges { - for _, e := range u { - uid := e.From().ID() - vid := e.To().ID() - if _, ok := seen[[2]int64{uid, vid}]; ok { - continue - } - seen[[2]int64{uid, vid}] = struct{}{} - seen[[2]int64{vid, uid}] = struct{}{} - edges = append(edges, e) - } - } - return edges -} - -// WeightedEdges returns all the weighted edges in the graph. -func (g *WeightedUndirectedGraph) WeightedEdges() []graph.WeightedEdge { - var edges []graph.WeightedEdge - seen := make(map[[2]int64]struct{}) - for _, u := range g.edges { - for _, e := range u { - uid := e.From().ID() - vid := e.To().ID() - if _, ok := seen[[2]int64{uid, vid}]; ok { - continue - } - seen[[2]int64{uid, vid}] = struct{}{} - seen[[2]int64{vid, uid}] = struct{}{} - edges = append(edges, e) - } - } - return edges -} - -// From returns all nodes in g that can be reached directly from n. -func (g *WeightedUndirectedGraph) From(id int64) []graph.Node { - if !g.Has(id) { - return nil - } - - nodes := make([]graph.Node, len(g.edges[id])) - i := 0 - for from := range g.edges[id] { - nodes[i] = g.nodes[from] - i++ - } - return nodes -} - -// HasEdgeBetween returns whether an edge exists between nodes x and y. -func (g *WeightedUndirectedGraph) HasEdgeBetween(xid, yid int64) bool { - _, ok := g.edges[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 *WeightedUndirectedGraph) Edge(uid, vid int64) graph.Edge { - return g.WeightedEdgeBetween(uid, vid) -} - -// WeightedEdge returns the weighted 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 *WeightedUndirectedGraph) WeightedEdge(uid, vid int64) graph.WeightedEdge { - return g.WeightedEdgeBetween(uid, vid) -} - -// EdgeBetween returns the edge between nodes x and y. -func (g *WeightedUndirectedGraph) EdgeBetween(xid, yid int64) graph.Edge { - return g.WeightedEdgeBetween(xid, yid) -} - -// WeightedEdgeBetween returns the weighted edge between nodes x and y. -func (g *WeightedUndirectedGraph) WeightedEdgeBetween(xid, yid int64) graph.WeightedEdge { - edge, ok := g.edges[xid][yid] - if !ok { - return nil - } - return edge -} - // 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 @@ -246,10 +232,42 @@ func (g *WeightedUndirectedGraph) Weight(xid, yid int64) (w float64, ok bool) { return g.absent, false } -// Degree returns the degree of n in g. -func (g *WeightedUndirectedGraph) Degree(id int64) int { - if _, ok := g.nodes[id]; !ok { - return 0 - } - return len(g.edges[id]) +// WeightedEdge returns the weighted 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 *WeightedUndirectedGraph) WeightedEdge(uid, vid int64) graph.WeightedEdge { + return g.WeightedEdgeBetween(uid, vid) +} + +// WeightedEdgeBetween returns the weighted edge between nodes x and y. +func (g *WeightedUndirectedGraph) WeightedEdgeBetween(xid, yid int64) graph.WeightedEdge { + edge, ok := g.edges[xid][yid] + if !ok { + return nil + } + if edge.From().ID() == xid { + return edge + } + return edge.ReversedEdge().(graph.WeightedEdge) +} + +// WeightedEdges returns all the weighted edges in the graph. +func (g *WeightedUndirectedGraph) WeightedEdges() graph.WeightedEdges { + var edges []graph.WeightedEdge + seen := make(map[[2]int64]struct{}) + for _, u := range g.edges { + for _, e := range u { + uid := e.From().ID() + vid := e.To().ID() + if _, ok := seen[[2]int64{uid, vid}]; ok { + continue + } + seen[[2]int64{uid, vid}] = struct{}{} + seen[[2]int64{vid, uid}] = struct{}{} + edges = append(edges, e) + } + } + if len(edges) == 0 { + return graph.Empty + } + return iterator.NewOrderedWeightedEdges(edges) } diff --git a/vendor/gonum.org/v1/gonum/graph/topo/BUILD b/vendor/gonum.org/v1/gonum/graph/topo/BUILD index fb26339b8dc..cc4d51f75f2 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/BUILD +++ b/vendor/gonum.org/v1/gonum/graph/topo/BUILD @@ -20,6 +20,7 @@ go_library( "//vendor/gonum.org/v1/gonum/graph/internal/linear:go_default_library", "//vendor/gonum.org/v1/gonum/graph/internal/ordered:go_default_library", "//vendor/gonum.org/v1/gonum/graph/internal/set:go_default_library", + "//vendor/gonum.org/v1/gonum/graph/iterator:go_default_library", "//vendor/gonum.org/v1/gonum/graph/traverse:go_default_library", ], ) diff --git a/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go b/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go index c602b13a8e2..83fdb5bdf8b 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go +++ b/vendor/gonum.org/v1/gonum/graph/topo/bron_kerbosch.go @@ -44,7 +44,7 @@ func KCore(k int, g graph.Undirected) []graph.Node { // s, a set of relative offsets into l for each k-core, where k is an index // into s. func degeneracyOrdering(g graph.Undirected) (l []graph.Node, s []int) { - nodes := g.Nodes() + nodes := graph.NodesOf(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 @@ -61,7 +61,7 @@ func degeneracyOrdering(g graph.Undirected) (l []graph.Node, s []int) { ) for _, n := range nodes { id := n.ID() - adj := g.From(id) + adj := graph.NodesOf(g.From(id)) neighbours[id] = adj dv[id] = len(adj) if len(adj) > maxDegree { @@ -133,26 +133,26 @@ func degeneracyOrdering(g graph.Undirected) (l []graph.Node, s []int) { // BronKerbosch returns the set of maximal cliques of the undirected graph g. func BronKerbosch(g graph.Undirected) [][]graph.Node { - nodes := g.Nodes() + nodes := graph.NodesOf(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)) + p := set.NewNodesSize(len(nodes)) for _, n := range nodes { p.Add(n) } - x := make(set.Nodes) + x := set.NewNodes() var bk bronKerbosch order, _ := degeneracyOrdering(g) ordered.Reverse(order) for _, v := range order { - neighbours := g.From(v.ID()) - nv := make(set.Nodes, len(neighbours)) + neighbours := graph.NodesOf(g.From(v.ID())) + nv := set.NewNodesSize(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)) + bk.maximalCliquePivot(g, []graph.Node{v}, set.IntersectionOfNodes(p, nv), set.IntersectionOfNodes(x, nv)) p.Remove(v) x.Add(v) } @@ -168,7 +168,7 @@ func (bk *bronKerbosch) maximalCliquePivot(g graph.Undirected, r []graph.Node, p } neighbours := bk.choosePivotFrom(g, p, x) - nu := make(set.Nodes, len(neighbours)) + nu := set.NewNodesSize(len(neighbours)) for _, n := range neighbours { nu.Add(n) } @@ -177,8 +177,8 @@ func (bk *bronKerbosch) maximalCliquePivot(g graph.Undirected, r []graph.Node, p continue } vid := v.ID() - neighbours := g.From(vid) - nv := make(set.Nodes, len(neighbours)) + neighbours := graph.NodesOf(g.From(vid)) + nv := set.NewNodesSize(len(neighbours)) for _, n := range neighbours { nv.Add(n) } @@ -195,7 +195,7 @@ func (bk *bronKerbosch) maximalCliquePivot(g graph.Undirected, r []graph.Node, p sr = append(r[:len(r):len(r)], v) } - bk.maximalCliquePivot(g, sr, make(set.Nodes).Intersect(p, nv), make(set.Nodes).Intersect(x, nv)) + bk.maximalCliquePivot(g, sr, set.IntersectionOfNodes(p, nv), set.IntersectionOfNodes(x, nv)) p.Remove(v) x.Add(v) } @@ -207,10 +207,10 @@ func (*bronKerbosch) choosePivotFrom(g graph.Undirected, p, x set.Nodes) (neighb // compile time option. if !tomitaTanakaTakahashi { for _, n := range p { - return g.From(n.ID()) + return graph.NodesOf(g.From(n.ID())) } for _, n := range x { - return g.From(n.ID()) + return graph.NodesOf(g.From(n.ID())) } panic("bronKerbosch: empty set") } @@ -222,7 +222,7 @@ func (*bronKerbosch) choosePivotFrom(g graph.Undirected, p, x set.Nodes) (neighb maxNeighbors := func(s set.Nodes) { outer: for _, u := range s { - nb := g.From(u.ID()) + nb := graph.NodesOf(g.From(u.ID())) c := len(nb) if c <= max { continue diff --git a/vendor/gonum.org/v1/gonum/graph/topo/clique_graph.go b/vendor/gonum.org/v1/gonum/graph/topo/clique_graph.go index 60ec75f064d..28f1b96ee7d 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/clique_graph.go +++ b/vendor/gonum.org/v1/gonum/graph/topo/clique_graph.go @@ -34,7 +34,7 @@ func CliqueGraph(dst Builder, g graph.Undirected) { cliqueNodes := make(cliqueNodeSets, len(cliques)) for id, c := range cliques { - s := make(set.Nodes, len(c)) + s := set.NewNodesSize(len(c)) for _, n := range c { s.Add(n) } @@ -58,7 +58,7 @@ func CliqueGraph(dst Builder, g graph.Undirected) { case len(vc.Clique.nodes): edgeNodes = []graph.Node{vc.Clique.nodes[0]} default: - for _, n := range make(set.Nodes).Intersect(uc.nodes, vc.nodes) { + for _, n := range set.IntersectionOfNodes(uc.nodes, vc.nodes) { edgeNodes = append(edgeNodes, n) } sort.Sort(ordered.ByID(edgeNodes)) @@ -101,6 +101,11 @@ func (e CliqueGraphEdge) From() graph.Node { return e.from } // To returns the to node of the edge. func (e CliqueGraphEdge) To() graph.Node { return e.to } +// ReversedEdge returns a new CliqueGraphEdge with +// the edge end points swapped. The nodes of the +// new edge are shared with the receiver. +func (e CliqueGraphEdge) ReversedEdge() graph.Edge { e.from, e.to = e.to, e.from; return e } + // Nodes returns the common nodes in the cliques of the underlying graph // corresponding to the from and to nodes in the clique graph. func (e CliqueGraphEdge) Nodes() []graph.Node { return e.nodes } diff --git a/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go b/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go index 8122a57edac..8a78ba2f39e 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go +++ b/vendor/gonum.org/v1/gonum/graph/topo/johnson_cycles.go @@ -10,6 +10,7 @@ import ( "gonum.org/v1/gonum/graph" "gonum.org/v1/gonum/graph/internal/ordered" "gonum.org/v1/gonum/graph/internal/set" + "gonum.org/v1/gonum/graph/iterator" ) // johnson implements Johnson's "Finding all the elementary @@ -132,7 +133,7 @@ type johnsonGraph struct { // johnsonGraphFrom returns a deep copy of the graph g. func johnsonGraphFrom(g graph.Directed) johnsonGraph { - nodes := g.Nodes() + nodes := graph.NodesOf(g.Nodes()) sort.Sort(ordered.ByID(nodes)) c := johnsonGraph{ orig: nodes, @@ -144,7 +145,7 @@ func johnsonGraphFrom(g graph.Directed) johnsonGraph { for i, u := range nodes { uid := u.ID() c.index[uid] = i - for _, v := range g.From(uid) { + for _, v := range graph.NodesOf(g.From(uid)) { if c.succ[uid] == nil { c.succ[uid] = make(set.Int64s) c.nodes.Add(uid) @@ -239,30 +240,33 @@ func (g johnsonGraph) sccSubGraph(sccs [][]graph.Node, min int) johnsonGraph { } // Nodes is required to satisfy Tarjan. -func (g johnsonGraph) Nodes() []graph.Node { +func (g johnsonGraph) Nodes() graph.Nodes { n := make([]graph.Node, 0, len(g.nodes)) for id := range g.nodes { n = append(n, johnsonGraphNode(id)) } - return n + return iterator.NewOrderedNodes(n) } // Successors is required to satisfy Tarjan. -func (g johnsonGraph) From(id int64) []graph.Node { +func (g johnsonGraph) From(id int64) graph.Nodes { adj := g.succ[id] if len(adj) == 0 { - return nil + return graph.Empty } succ := make([]graph.Node, 0, len(adj)) for id := range adj { succ = append(succ, johnsonGraphNode(id)) } - return succ + return iterator.NewOrderedNodes(succ) } func (johnsonGraph) Has(int64) bool { panic("topo: unintended use of johnsonGraph") } +func (johnsonGraph) Node(int64) graph.Node { + panic("topo: unintended use of johnsonGraph") +} func (johnsonGraph) HasEdgeBetween(_, _ int64) bool { panic("topo: unintended use of johnsonGraph") } @@ -272,7 +276,7 @@ func (johnsonGraph) Edge(_, _ int64) graph.Edge { func (johnsonGraph) HasEdgeFromTo(_, _ int64) bool { panic("topo: unintended use of johnsonGraph") } -func (johnsonGraph) To(int64) []graph.Node { +func (johnsonGraph) To(int64) graph.Nodes { panic("topo: unintended use of johnsonGraph") } diff --git a/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go b/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go index 5d4d0751ca1..44b362a6fd6 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go +++ b/vendor/gonum.org/v1/gonum/graph/topo/paton_cycles.go @@ -19,7 +19,9 @@ func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node { var cycles [][]graph.Node done := make(set.Int64s) var tree linear.NodeStack - for _, n := range g.Nodes() { + nodes := g.Nodes() + for nodes.Next() { + n := nodes.Node() id := n.ID() if done.Has(id) { continue @@ -35,7 +37,7 @@ func UndirectedCyclesIn(g graph.Undirected) [][]graph.Node { u := tree.Pop() uid := u.ID() adj := from[uid] - for _, v := range g.From(uid) { + for _, v := range graph.NodesOf(g.From(uid)) { vid := v.ID() switch { case uid == vid: diff --git a/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go b/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go index 28f50e24ba0..64712927585 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go +++ b/vendor/gonum.org/v1/gonum/graph/topo/tarjan.go @@ -94,16 +94,18 @@ func TarjanSCC(g graph.Directed) [][]graph.Node { } func tarjanSCCstabilized(g graph.Directed, order func([]graph.Node)) [][]graph.Node { - nodes := g.Nodes() + nodes := graph.NodesOf(g.Nodes()) var succ func(id int64) []graph.Node if order == nil { - succ = g.From + succ = func(id int64) []graph.Node { + return graph.NodesOf(g.From(id)) + } } else { order(nodes) ordered.Reverse(nodes) succ = func(id int64) []graph.Node { - to := g.From(id) + to := graph.NodesOf(g.From(id)) order(to) ordered.Reverse(to) return to diff --git a/vendor/gonum.org/v1/gonum/graph/topo/topo.go b/vendor/gonum.org/v1/gonum/graph/topo/topo.go index 80945cf695d..bece61a6ca6 100644 --- a/vendor/gonum.org/v1/gonum/graph/topo/topo.go +++ b/vendor/gonum.org/v1/gonum/graph/topo/topo.go @@ -18,7 +18,7 @@ func IsPathIn(g graph.Graph, path []graph.Node) bool { case 0: return true case 1: - return g.Has(path[0].ID()) + return g.Node(path[0].ID()) != nil default: var canReach func(uid, vid int64) bool switch g := g.(type) { diff --git a/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go b/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go index 2f486bae8e5..125b16114c3 100644 --- a/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go +++ b/vendor/gonum.org/v1/gonum/graph/traverse/traverse.go @@ -16,33 +16,45 @@ var _ Graph = graph.Graph(nil) type Graph interface { // From returns all nodes that can be reached directly // from the node with the given ID. - From(id int64) []graph.Node + From(id int64) graph.Nodes // Edge returns the edge from u to v, with IDs uid and vid, // if such an edge exists and nil otherwise. The node v - // must be directly reachable from u as defined by the - // From method. + // must be directly reachable from u as defined by + // the From method. Edge(uid, vid int64) graph.Edge } // 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 set.Int64s + // Visit is called on all nodes on their first visit. + Visit func(graph.Node) + + // Traverse is called on all edges that may be traversed + // during the walk. This includes edges that would hop to + // an already visited node. + // + // The value returned by Traverse determines whether + // an edge can be traversed during the walk. + Traverse func(graph.Edge) bool + + queue linear.NodeQueue + visited set.Int64s } // 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 +// depending on the Traverse field and the until parameter if they are non-nil. +// The traversal follows edges for which Traverse(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. +// non-nil, it is called with each node the first time it is visited. func (b *BreadthFirst) Walk(g Graph, from graph.Node, until func(n graph.Node, d int) bool) graph.Node { if b.visited == nil { b.visited = make(set.Int64s) } b.queue.Enqueue(from) + if b.Visit != nil && !b.visited.Has(from.ID()) { + b.Visit(from) + } b.visited.Add(from.ID()) var ( @@ -56,16 +68,18 @@ func (b *BreadthFirst) Walk(g Graph, from graph.Node, until func(n graph.Node, d return t } tid := t.ID() - for _, n := range g.From(tid) { + to := g.From(tid) + for to.Next() { + n := to.Node() nid := n.ID() - if b.EdgeFilter != nil && !b.EdgeFilter(g.Edge(tid, nid)) { + if b.Traverse != nil && !b.Traverse(g.Edge(tid, nid)) { continue } if b.visited.Has(nid) { continue } if b.Visit != nil { - b.Visit(t, n) + b.Visit(n) } b.visited.Add(nid) children++ @@ -87,7 +101,9 @@ func (b *BreadthFirst) Walk(g Graph, from graph.Node, until func(n graph.Node, d // 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() { + nodes := g.Nodes() + for nodes.Next() { + from := nodes.Node() if b.Visited(from) { continue } @@ -119,22 +135,34 @@ func (b *BreadthFirst) Reset() { // 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 set.Int64s + // Visit is called on all nodes on their first visit. + Visit func(graph.Node) + + // Traverse is called on all edges that may be traversed + // during the walk. This includes edges that would hop to + // an already visited node. + // + // The value returned by Traverse determines whether an + // edge can be traversed during the walk. + Traverse func(graph.Edge) bool + + stack linear.NodeStack + visited set.Int64s } // 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 +// depending on the Traverse field and the until parameter if they are non-nil. +// The traversal follows edges for which Traverse(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. +// is called with each node the first time it is visited. func (d *DepthFirst) Walk(g Graph, from graph.Node, until func(graph.Node) bool) graph.Node { if d.visited == nil { d.visited = make(set.Int64s) } d.stack.Push(from) + if d.Visit != nil && !d.visited.Has(from.ID()) { + d.Visit(from) + } d.visited.Add(from.ID()) for d.stack.Len() > 0 { @@ -143,16 +171,18 @@ func (d *DepthFirst) Walk(g Graph, from graph.Node, until func(graph.Node) bool) return t } tid := t.ID() - for _, n := range g.From(tid) { + to := g.From(tid) + for to.Next() { + n := to.Node() nid := n.ID() - if d.EdgeFilter != nil && !d.EdgeFilter(g.Edge(tid, nid)) { + if d.Traverse != nil && !d.Traverse(g.Edge(tid, nid)) { continue } if d.visited.Has(nid) { continue } if d.Visit != nil { - d.Visit(t, n) + d.Visit(n) } d.visited.Add(nid) d.stack.Push(n) @@ -168,7 +198,9 @@ func (d *DepthFirst) Walk(g Graph, from graph.Node, until func(graph.Node) bool) // 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() { + nodes := g.Nodes() + for nodes.Next() { + from := nodes.Node() if d.Visited(from) { continue } diff --git a/vendor/gonum.org/v1/gonum/graph/undirect.go b/vendor/gonum.org/v1/gonum/graph/undirect.go index 49ba62bdb7f..07ce64a0605 100644 --- a/vendor/gonum.org/v1/gonum/graph/undirect.go +++ b/vendor/gonum.org/v1/gonum/graph/undirect.go @@ -11,29 +11,16 @@ type Undirect struct { var _ Undirected = Undirect{} -// Has returns whether the node exists within the graph. -func (g Undirect) Has(id int64) bool { return g.G.Has(id) } +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g Undirect) Node(id int64) Node { return g.G.Node(id) } // Nodes returns all the nodes in the graph. -func (g Undirect) Nodes() []Node { return g.G.Nodes() } +func (g Undirect) Nodes() Nodes { return g.G.Nodes() } // From returns all nodes in g that can be reached directly from u. -func (g Undirect) From(uid int64) []Node { - var nodes []Node - seen := make(map[int64]struct{}) - for _, n := range g.G.From(uid) { - seen[n.ID()] = struct{}{} - nodes = append(nodes, n) - } - for _, n := range g.G.To(uid) { - id := n.ID() - if _, ok := seen[id]; ok { - continue - } - seen[n.ID()] = struct{}{} - nodes = append(nodes, n) - } - return nodes +func (g Undirect) From(uid int64) Nodes { + return newNodeFilterIterator(g.G.From(uid), g.G.To(uid)) } // HasEdgeBetween returns whether an edge exists between nodes x and y. @@ -90,29 +77,16 @@ var ( _ WeightedUndirected = UndirectWeighted{} ) -// Has returns whether the node exists within the graph. -func (g UndirectWeighted) Has(id int64) bool { return g.G.Has(id) } +// Node returns the node with the given ID if it exists in the graph, +// and nil otherwise. +func (g UndirectWeighted) Node(id int64) Node { return g.G.Node(id) } // Nodes returns all the nodes in the graph. -func (g UndirectWeighted) Nodes() []Node { return g.G.Nodes() } +func (g UndirectWeighted) Nodes() Nodes { return g.G.Nodes() } // From returns all nodes in g that can be reached directly from u. -func (g UndirectWeighted) From(uid int64) []Node { - var nodes []Node - seen := make(map[int64]struct{}) - for _, n := range g.G.From(uid) { - seen[n.ID()] = struct{}{} - nodes = append(nodes, n) - } - for _, n := range g.G.To(uid) { - id := n.ID() - if _, ok := seen[id]; ok { - continue - } - seen[n.ID()] = struct{}{} - nodes = append(nodes, n) - } - return nodes +func (g UndirectWeighted) From(uid int64) Nodes { + return newNodeFilterIterator(g.G.From(uid), g.G.To(uid)) } // HasEdgeBetween returns whether an edge exists between nodes x and y. @@ -216,11 +190,81 @@ func (e EdgePair) To() Node { return nil } +// ReversedEdge returns a new Edge with the end point of the +// edges in the pair swapped. +func (e EdgePair) ReversedEdge() Edge { + if e[0] != nil { + e[0] = e[0].ReversedEdge() + } + if e[1] != nil { + e[1] = e[1].ReversedEdge() + } + return e +} + // WeightedEdgePair is an opposed pair of directed edges. type WeightedEdgePair struct { EdgePair W float64 } +// ReversedEdge returns a new Edge with the end point of the +// edges in the pair swapped. +func (e WeightedEdgePair) ReversedEdge() Edge { + e.EdgePair = e.EdgePair.ReversedEdge().(EdgePair) + return e +} + // Weight returns the merged edge weights of the two edges. func (e WeightedEdgePair) Weight() float64 { return e.W } + +// nodeFilterIterator combines two Nodes to produce a single stream of +// unique nodes. +type nodeFilterIterator struct { + a, b Nodes + + // unique indicates the node in b with the key ID is unique. + unique map[int64]bool +} + +func newNodeFilterIterator(a, b Nodes) *nodeFilterIterator { + n := nodeFilterIterator{a: a, b: b, unique: make(map[int64]bool)} + for n.b.Next() { + n.unique[n.b.Node().ID()] = true + } + n.b.Reset() + for n.a.Next() { + n.unique[n.a.Node().ID()] = false + } + n.a.Reset() + return &n +} + +func (n *nodeFilterIterator) Len() int { + return len(n.unique) +} + +func (n *nodeFilterIterator) Next() bool { + n.Len() + if n.a.Next() { + return true + } + for n.b.Next() { + if n.unique[n.b.Node().ID()] { + return true + } + } + return false +} + +func (n *nodeFilterIterator) Node() Node { + if n.a.Len() != 0 { + return n.a.Node() + } + return n.b.Node() +} + +func (n *nodeFilterIterator) Reset() { + n.a.Reset() + n.b.Reset() +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/BUILD b/vendor/gonum.org/v1/gonum/internal/asm/c64/BUILD new file mode 100644 index 00000000000..817807ea069 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/BUILD @@ -0,0 +1,37 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "axpyinc_amd64.s", + "axpyincto_amd64.s", + "axpyunitary_amd64.s", + "axpyunitaryto_amd64.s", + "conj.go", + "doc.go", + "dotcinc_amd64.s", + "dotcunitary_amd64.s", + "dotuinc_amd64.s", + "dotuunitary_amd64.s", + "scal.go", + "stubs_amd64.go", + "stubs_noasm.go", + ], + importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/internal/asm/c64", + importpath = "gonum.org/v1/gonum/internal/asm/c64", + visibility = ["//vendor/gonum.org/v1/gonum:__subpackages__"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyinc_amd64.s new file mode 100644 index 00000000000..841415dbc9f --- /dev/null +++ b/vendor/gonum.org/v1/gonum/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,!safe + +#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/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyincto_amd64.s new file mode 100644 index 00000000000..5c5228dc21d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/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,!safe + +#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/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitary_amd64.s new file mode 100644 index 00000000000..ae744a4902e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/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,!safe + +#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/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/axpyunitaryto_amd64.s new file mode 100644 index 00000000000..a5d702092d0 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/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,!safe + +#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/vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go similarity index 66% rename from vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go rename to vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go index 2eb7f9c3327..910e1e5c732 100644 --- a/vendor/gonum.org/v1/gonum/graph/encoding/dot/dot.go +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/conj.go @@ -2,4 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package dot +package c64 + +func conj(c complex64) complex64 { return complex(real(c), -imag(c)) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/doc.go new file mode 100644 index 00000000000..35f1b2a26b3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/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 // import "gonum.org/v1/gonum/internal/asm/c64" diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_amd64.s new file mode 100644 index 00000000000..87de31d32a8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcinc_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,!safe + +#include "textflag.h" + +#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 +#define MOVSHDUP_X5_X4 LONG $0xE5160FF3 // MOVSHDUP X5, X4 +#define MOVSHDUP_X7_X6 LONG $0xF7160FF3 // MOVSHDUP X7, X6 +#define MOVSHDUP_X9_X8 LONG $0x160F45F3; BYTE $0xC1 // MOVSHDUP X9, X8 + +#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 +#define MOVSLDUP_X5_X5 LONG $0xED120FF3 // MOVSLDUP X5, X5 +#define MOVSLDUP_X7_X7 LONG $0xFF120FF3 // MOVSLDUP X7, X7 +#define MOVSLDUP_X9_X9 LONG $0x120F45F3; BYTE $0xC9 // MOVSLDUP X9, X9 + +#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 +#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 +#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 +#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 + +#define X_PTR SI +#define Y_PTR DI +#define LEN CX +#define TAIL BX +#define SUM X0 +#define P_SUM X1 +#define INC_X R8 +#define INCx3_X R9 +#define INC_Y R10 +#define INCx3_Y R11 +#define NEG1 X15 +#define P_NEG1 X14 + +// func DotcInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) +TEXT ·DotcInc(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), X_PTR // X_PTR = &x + MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y + PXOR SUM, SUM // SUM = 0 + PXOR P_SUM, P_SUM // P_SUM = 0 + MOVQ n+48(FP), LEN // LEN = n + CMPQ LEN, $0 // if LEN == 0 { return } + JE dotc_end + MOVQ ix+72(FP), INC_X + MOVQ iy+80(FP), INC_Y + LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(X_PTR[ix]) + LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(Y_PTR[iy]) + MOVQ incX+56(FP), INC_X // INC_X = incX * sizeof(complex64) + SHLQ $3, INC_X + MOVQ incY+64(FP), INC_Y // INC_Y = incY * sizeof(complex64) + SHLQ $3, INC_Y + MOVSS $(-1.0), NEG1 + SHUFPS $0, NEG1, NEG1 // { -1, -1, -1, -1 } + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = LEN % 4 + SHRQ $2, LEN // LEN = floor( LEN / 4 ) + JZ dotc_tail // if LEN == 0 { goto dotc_tail } + + MOVUPS NEG1, P_NEG1 // Copy NEG1 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 + +dotc_loop: // do { + MOVSD (X_PTR), X3 // X_i = { imag(x[i]), real(x[i]) } + MOVSD (X_PTR)(INC_X*1), X5 + MOVSD (X_PTR)(INC_X*2), X7 + MOVSD (X_PTR)(INCx3_X*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) = { -imag(x[i]), -imag(x[i]) } + MULPS NEG1, X2 + MULPS P_NEG1, X4 + MULPS NEG1, X6 + MULPS P_NEG1, X8 + + // X_j = { imag(y[i]), real(y[i]) } + MOVSD (Y_PTR), X10 + MOVSD (Y_PTR)(INC_Y*1), X11 + MOVSD (Y_PTR)(INC_Y*2), X12 + MOVSD (Y_PTR)(INCx3_Y*1), X13 + + // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + MULPS X10, X3 + MULPS X11, X5 + MULPS X12, X7 + MULPS X13, X9 + + // X_j = { real(y[i]), imag(y[i]) } + SHUFPS $0xB1, X10, X10 + SHUFPS $0xB1, X11, X11 + SHUFPS $0xB1, X12, X12 + SHUFPS $0xB1, X13, X13 + + // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + MULPS X10, X2 + MULPS X11, X4 + MULPS X12, X6 + MULPS X13, X8 + + // X_i = { + // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), + // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]) } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // SUM += X_i + ADDPS X3, SUM + ADDPS X5, P_SUM + ADDPS X7, SUM + ADDPS X9, P_SUM + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X*4]) + LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y*4]) + + DECQ LEN + JNZ dotc_loop // } while --LEN > 0 + + ADDPS P_SUM, SUM // SUM = { P_SUM + SUM } + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE dotc_end + +dotc_tail: // do { + MOVSD (X_PTR), 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]) } + MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } + MOVUPS (Y_PTR), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + ADDPS X3, SUM // SUM += X_i + ADDQ INC_X, X_PTR // X_PTR += INC_X + ADDQ INC_Y, Y_PTR // Y_PTR += INC_Y + DECQ TAIL + JNZ dotc_tail // } while --TAIL > 0 + +dotc_end: + MOVSD SUM, sum+88(FP) // return SUM + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s new file mode 100644 index 00000000000..d53479ca49c --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotcunitary_amd64.s @@ -0,0 +1,208 @@ +// 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 !noasm,!appengine,!safe + +#include "textflag.h" + +#define MOVSLDUP_XPTR_IDX_8__X3 LONG $0x1C120FF3; BYTE $0xC6 // MOVSLDUP (SI)(AX*8), X3 +#define MOVSLDUP_16_XPTR_IDX_8__X5 LONG $0x6C120FF3; WORD $0x10C6 // MOVSLDUP 16(SI)(AX*8), X5 +#define MOVSLDUP_32_XPTR_IDX_8__X7 LONG $0x7C120FF3; WORD $0x20C6 // MOVSLDUP 32(SI)(AX*8), X7 +#define MOVSLDUP_48_XPTR_IDX_8__X9 LONG $0x120F44F3; WORD $0xC64C; BYTE $0x30 // MOVSLDUP 48(SI)(AX*8), X9 + +#define MOVSHDUP_XPTR_IDX_8__X2 LONG $0x14160FF3; BYTE $0xC6 // MOVSHDUP (SI)(AX*8), X2 +#define MOVSHDUP_16_XPTR_IDX_8__X4 LONG $0x64160FF3; WORD $0x10C6 // MOVSHDUP 16(SI)(AX*8), X4 +#define MOVSHDUP_32_XPTR_IDX_8__X6 LONG $0x74160FF3; WORD $0x20C6 // MOVSHDUP 32(SI)(AX*8), X6 +#define MOVSHDUP_48_XPTR_IDX_8__X8 LONG $0x160F44F3; WORD $0xC644; BYTE $0x30 // MOVSHDUP 48(SI)(AX*8), X8 + +#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 +#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 + +#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 +#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 +#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 +#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 + +#define X_PTR SI +#define Y_PTR DI +#define LEN CX +#define TAIL BX +#define SUM X0 +#define P_SUM X1 +#define IDX AX +#define I_IDX DX +#define NEG1 X15 +#define P_NEG1 X14 + +// func DotcUnitary(x, y []complex64) (sum complex64) +TEXT ·DotcUnitary(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), X_PTR // X_PTR = &x + MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y + PXOR SUM, SUM // SUM = 0 + PXOR P_SUM, P_SUM // P_SUM = 0 + MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) + CMPQ y_len+32(FP), LEN + CMOVQLE y_len+32(FP), LEN + CMPQ LEN, $0 // if LEN == 0 { return } + JE dotc_end + XORQ IDX, IDX // i = 0 + MOVSS $(-1.0), NEG1 + SHUFPS $0, NEG1, NEG1 // { -1, -1, -1, -1 } + + MOVQ X_PTR, DX + ANDQ $15, DX // DX = &x & 15 + JZ dotc_aligned // if DX == 0 { goto dotc_aligned } + + MOVSD (X_PTR)(IDX*8), 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]) } + MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + + MOVAPS X3, SUM // SUM = X_i + INCQ IDX // IDX++ + DECQ LEN // LEN-- + JZ dotc_ret // if LEN == 0 { goto dotc_ret } + +dotc_aligned: + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL = LEN % 8 + SHRQ $3, LEN // LEN = floor( LEN / 8 ) + JZ dotc_tail // if LEN == 0 { return } + MOVUPS NEG1, P_NEG1 // Copy NEG1 for pipelining + +dotc_loop: // do { + MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSLDUP_16_XPTR_IDX_8__X5 + MOVSLDUP_32_XPTR_IDX_8__X7 + MOVSLDUP_48_XPTR_IDX_8__X9 + + MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i+1]), imag(x[i+1]) } + MOVSHDUP_16_XPTR_IDX_8__X4 + MOVSHDUP_32_XPTR_IDX_8__X6 + MOVSHDUP_48_XPTR_IDX_8__X8 + + // X_j = { imag(y[i]), real(y[i]), imag(y[i+1]), real(y[i+1]) } + MOVUPS (Y_PTR)(IDX*8), X10 + MOVUPS 16(Y_PTR)(IDX*8), X11 + MOVUPS 32(Y_PTR)(IDX*8), X12 + MOVUPS 48(Y_PTR)(IDX*8), X13 + + // X_(i-1) = { -imag(x[i]), -imag(x[i]), -imag(x[i]+1), -imag(x[i]+1) } + MULPS NEG1, X2 + MULPS P_NEG1, X4 + MULPS NEG1, X6 + MULPS P_NEG1, X8 + + // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]), + // imag(y[i+1]) * real(x[i+1]), real(y[i+1]) * real(x[i+1]) } + MULPS X10, X3 + MULPS X11, X5 + MULPS X12, X7 + MULPS X13, X9 + + // X_j = { real(y[i]), imag(y[i]), real(y[i+1]), imag(y[i+1]) } + SHUFPS $0xB1, X10, X10 + SHUFPS $0xB1, X11, X11 + SHUFPS $0xB1, X12, X12 + SHUFPS $0xB1, X13, X13 + + // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]), + // real(y[i+1]) * imag(x[i+1]), imag(y[i+1]) * imag(x[i+1]) } + MULPS X10, X2 + MULPS X11, X4 + MULPS X12, X6 + MULPS X13, X8 + + // X_i = { + // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), + // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]), + // imag(result[i+1]): imag(y[i+1]) * real(x[i+1]) + real(y[i+1]) * imag(x[i+1]), + // real(result[i+1]): real(y[i+1]) * real(x[i+1]) - imag(y[i+1]) * imag(x[i+1]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // SUM += X_i + ADDPS X3, SUM + ADDPS X5, P_SUM + ADDPS X7, SUM + ADDPS X9, P_SUM + + ADDQ $8, IDX // IDX += 8 + DECQ LEN + JNZ dotc_loop // } while --LEN > 0 + + ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } + XORPS SUM, SUM // SUM = 0 + + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE dotc_end + +dotc_tail: + MOVQ TAIL, LEN + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ dotc_tail_one // if LEN == 0 { goto dotc_tail_one } + +dotc_tail_two: // do { + MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVUPS (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0xB1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + + ADDPS X3, SUM // SUM += X_i + + ADDQ $2, IDX // IDX += 2 + DECQ LEN + JNZ dotc_tail_two // } while --LEN > 0 + + ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } + XORPS SUM, SUM // SUM = 0 + + ANDQ $1, TAIL + JZ dotc_end + +dotc_tail_one: + MOVSD (X_PTR)(IDX*8), 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]) } + MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS NEG1, X2 // X_(i-1) = { -imag(x[i]), imag(x[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + + ADDPS X3, SUM // SUM += X_i + +dotc_end: + ADDPS P_SUM, SUM // SUM = { P_SUM[0] + SUM[0] } + MOVHLPS P_SUM, P_SUM // P_SUM = { P_SUM[1], P_SUM[1] } + ADDPS P_SUM, SUM // SUM = { P_SUM[1] + SUM[0] } + +dotc_ret: + MOVSD SUM, sum+48(FP) // return SUM + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s new file mode 100644 index 00000000000..bdee59becd8 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuinc_amd64.s @@ -0,0 +1,148 @@ +// 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,!safe + +#include "textflag.h" + +#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 +#define MOVSHDUP_X5_X4 LONG $0xE5160FF3 // MOVSHDUP X5, X4 +#define MOVSHDUP_X7_X6 LONG $0xF7160FF3 // MOVSHDUP X7, X6 +#define MOVSHDUP_X9_X8 LONG $0x160F45F3; BYTE $0xC1 // MOVSHDUP X9, X8 + +#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 +#define MOVSLDUP_X5_X5 LONG $0xED120FF3 // MOVSLDUP X5, X5 +#define MOVSLDUP_X7_X7 LONG $0xFF120FF3 // MOVSLDUP X7, X7 +#define MOVSLDUP_X9_X9 LONG $0x120F45F3; BYTE $0xC9 // MOVSLDUP X9, X9 + +#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 +#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 +#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 +#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 + +#define X_PTR SI +#define Y_PTR DI +#define LEN CX +#define TAIL BX +#define SUM X0 +#define P_SUM X1 +#define INC_X R8 +#define INCx3_X R9 +#define INC_Y R10 +#define INCx3_Y R11 + +// func DotuInc(x, y []complex64, n, incX, incY, ix, iy uintptr) (sum complex64) +TEXT ·DotuInc(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), X_PTR // X_PTR = &x + MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y + PXOR SUM, SUM // SUM = 0 + PXOR P_SUM, P_SUM // P_SUM = 0 + MOVQ n+48(FP), LEN // LEN = n + CMPQ LEN, $0 // if LEN == 0 { return } + JE dotu_end + MOVQ ix+72(FP), INC_X + MOVQ iy+80(FP), INC_Y + LEAQ (X_PTR)(INC_X*8), X_PTR // X_PTR = &(X_PTR[ix]) + LEAQ (Y_PTR)(INC_Y*8), Y_PTR // Y_PTR = &(Y_PTR[iy]) + MOVQ incX+56(FP), INC_X // INC_X = incX * sizeof(complex64) + SHLQ $3, INC_X + MOVQ incY+64(FP), INC_Y // INC_Y = incY * sizeof(complex64) + SHLQ $3, INC_Y + + MOVQ LEN, TAIL + ANDQ $3, TAIL // TAIL = LEN % 4 + SHRQ $2, LEN // LEN = floor( LEN / 4 ) + JZ dotu_tail // if TAIL == 0 { goto dotu_tail } + + 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 + +dotu_loop: // do { + MOVSD (X_PTR), X3 // X_i = { imag(x[i]), real(x[i]) } + MOVSD (X_PTR)(INC_X*1), X5 + MOVSD (X_PTR)(INC_X*2), X7 + MOVSD (X_PTR)(INCx3_X*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_j = { imag(y[i]), real(y[i]) } + MOVSD (Y_PTR), X10 + MOVSD (Y_PTR)(INC_Y*1), X11 + MOVSD (Y_PTR)(INC_Y*2), X12 + MOVSD (Y_PTR)(INCx3_Y*1), X13 + + // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + MULPS X10, X3 + MULPS X11, X5 + MULPS X12, X7 + MULPS X13, X9 + + // X_j = { real(y[i]), imag(y[i]) } + SHUFPS $0xB1, X10, X10 + SHUFPS $0xB1, X11, X11 + SHUFPS $0xB1, X12, X12 + SHUFPS $0xB1, X13, X13 + + // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + MULPS X10, X2 + MULPS X11, X4 + MULPS X12, X6 + MULPS X13, X8 + + // X_i = { + // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), + // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]) } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // SUM += X_i + ADDPS X3, SUM + ADDPS X5, P_SUM + ADDPS X7, SUM + ADDPS X9, P_SUM + + LEAQ (X_PTR)(INC_X*4), X_PTR // X_PTR = &(X_PTR[INC_X*4]) + LEAQ (Y_PTR)(INC_Y*4), Y_PTR // Y_PTR = &(Y_PTR[INC_Y*4]) + + DECQ LEN + JNZ dotu_loop // } while --LEN > 0 + + ADDPS P_SUM, SUM // SUM = { P_SUM + SUM } + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE dotu_end + +dotu_tail: // do { + MOVSD (X_PTR), 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]) } + MOVUPS (Y_PTR), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + ADDPS X3, SUM // SUM += X_i + ADDQ INC_X, X_PTR // X_PTR += INC_X + ADDQ INC_Y, Y_PTR // Y_PTR += INC_Y + DECQ TAIL + JNZ dotu_tail // } while --TAIL > 0 + +dotu_end: + MOVSD SUM, sum+88(FP) // return SUM + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s new file mode 100644 index 00000000000..dce83a46711 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/dotuunitary_amd64.s @@ -0,0 +1,197 @@ +// 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 !noasm,!appengine,!safe + +#include "textflag.h" + +#define MOVSLDUP_XPTR_IDX_8__X3 LONG $0x1C120FF3; BYTE $0xC6 // MOVSLDUP (SI)(AX*8), X3 +#define MOVSLDUP_16_XPTR_IDX_8__X5 LONG $0x6C120FF3; WORD $0x10C6 // MOVSLDUP 16(SI)(AX*8), X5 +#define MOVSLDUP_32_XPTR_IDX_8__X7 LONG $0x7C120FF3; WORD $0x20C6 // MOVSLDUP 32(SI)(AX*8), X7 +#define MOVSLDUP_48_XPTR_IDX_8__X9 LONG $0x120F44F3; WORD $0xC64C; BYTE $0x30 // MOVSLDUP 48(SI)(AX*8), X9 + +#define MOVSHDUP_XPTR_IDX_8__X2 LONG $0x14160FF3; BYTE $0xC6 // MOVSHDUP (SI)(AX*8), X2 +#define MOVSHDUP_16_XPTR_IDX_8__X4 LONG $0x64160FF3; WORD $0x10C6 // MOVSHDUP 16(SI)(AX*8), X4 +#define MOVSHDUP_32_XPTR_IDX_8__X6 LONG $0x74160FF3; WORD $0x20C6 // MOVSHDUP 32(SI)(AX*8), X6 +#define MOVSHDUP_48_XPTR_IDX_8__X8 LONG $0x160F44F3; WORD $0xC644; BYTE $0x30 // MOVSHDUP 48(SI)(AX*8), X8 + +#define MOVSHDUP_X3_X2 LONG $0xD3160FF3 // MOVSHDUP X3, X2 +#define MOVSLDUP_X3_X3 LONG $0xDB120FF3 // MOVSLDUP X3, X3 + +#define ADDSUBPS_X2_X3 LONG $0xDAD00FF2 // ADDSUBPS X2, X3 +#define ADDSUBPS_X4_X5 LONG $0xECD00FF2 // ADDSUBPS X4, X5 +#define ADDSUBPS_X6_X7 LONG $0xFED00FF2 // ADDSUBPS X6, X7 +#define ADDSUBPS_X8_X9 LONG $0xD00F45F2; BYTE $0xC8 // ADDSUBPS X8, X9 + +#define X_PTR SI +#define Y_PTR DI +#define LEN CX +#define TAIL BX +#define SUM X0 +#define P_SUM X1 +#define IDX AX +#define I_IDX DX +#define NEG1 X15 +#define P_NEG1 X14 + +// func DotuUnitary(x, y []complex64) (sum complex64) +TEXT ·DotuUnitary(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), X_PTR // X_PTR = &x + MOVQ y_base+24(FP), Y_PTR // Y_PTR = &y + PXOR SUM, SUM // SUM = 0 + PXOR P_SUM, P_SUM // P_SUM = 0 + MOVQ x_len+8(FP), LEN // LEN = min( len(x), len(y) ) + CMPQ y_len+32(FP), LEN + CMOVQLE y_len+32(FP), LEN + CMPQ LEN, $0 // if LEN == 0 { return } + JE dotu_end + XORQ IDX, IDX // IDX = 0 + + MOVQ X_PTR, DX + ANDQ $15, DX // DX = &x & 15 + JZ dotu_aligned // if DX == 0 { goto dotu_aligned } + + MOVSD (X_PTR)(IDX*8), 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]) } + MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + + MOVAPS X3, SUM // SUM = X_i + INCQ IDX // IDX++ + DECQ LEN // LEN-- + JZ dotu_end // if LEN == 0 { goto dotu_end } + +dotu_aligned: + MOVQ LEN, TAIL + ANDQ $7, TAIL // TAIL = LEN % 8 + SHRQ $3, LEN // LEN = floor( LEN / 8 ) + JZ dotu_tail // if LEN == 0 { goto dotu_tail } + PXOR P_SUM, P_SUM + +dotu_loop: // do { + MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSLDUP_16_XPTR_IDX_8__X5 + MOVSLDUP_32_XPTR_IDX_8__X7 + MOVSLDUP_48_XPTR_IDX_8__X9 + + MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVSHDUP_16_XPTR_IDX_8__X4 + MOVSHDUP_32_XPTR_IDX_8__X6 + MOVSHDUP_48_XPTR_IDX_8__X8 + + // X_j = { imag(y[i]), real(y[i]), imag(y[i+1]), real(y[i+1]) } + MOVUPS (Y_PTR)(IDX*8), X10 + MOVUPS 16(Y_PTR)(IDX*8), X11 + MOVUPS 32(Y_PTR)(IDX*8), X12 + MOVUPS 48(Y_PTR)(IDX*8), X13 + + // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]), + // imag(y[i+1]) * real(x[i+1]), real(y[i+1]) * real(x[i+1]) } + MULPS X10, X3 + MULPS X11, X5 + MULPS X12, X7 + MULPS X13, X9 + + // X_j = { real(y[i]), imag(y[i]), real(y[i+1]), imag(y[i+1]) } + SHUFPS $0xB1, X10, X10 + SHUFPS $0xB1, X11, X11 + SHUFPS $0xB1, X12, X12 + SHUFPS $0xB1, X13, X13 + + // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]), + // real(y[i+1]) * imag(x[i+1]), imag(y[i+1]) * imag(x[i+1]) } + MULPS X10, X2 + MULPS X11, X4 + MULPS X12, X6 + MULPS X13, X8 + + // X_i = { + // imag(result[i]): imag(y[i]) * real(x[i]) + real(y[i]) * imag(x[i]), + // real(result[i]): real(y[i]) * real(x[i]) - imag(y[i]) * imag(x[i]), + // imag(result[i+1]): imag(y[i+1]) * real(x[i+1]) + real(y[i+1]) * imag(x[i+1]), + // real(result[i+1]): real(y[i+1]) * real(x[i+1]) - imag(y[i+1]) * imag(x[i+1]), + // } + ADDSUBPS_X2_X3 + ADDSUBPS_X4_X5 + ADDSUBPS_X6_X7 + ADDSUBPS_X8_X9 + + // SUM += X_i + ADDPS X3, SUM + ADDPS X5, P_SUM + ADDPS X7, SUM + ADDPS X9, P_SUM + + ADDQ $8, IDX // IDX += 8 + DECQ LEN + JNZ dotu_loop // } while --LEN > 0 + + ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } + XORPS SUM, SUM // SUM = 0 + + CMPQ TAIL, $0 // if TAIL == 0 { return } + JE dotu_end + +dotu_tail: + MOVQ TAIL, LEN + SHRQ $1, LEN // LEN = floor( LEN / 2 ) + JZ dotu_tail_one // if LEN == 0 { goto dotc_tail_one } + +dotu_tail_two: // do { + MOVSLDUP_XPTR_IDX_8__X3 // X_i = { real(x[i]), real(x[i]), real(x[i+1]), real(x[i+1]) } + MOVSHDUP_XPTR_IDX_8__X2 // X_(i-1) = { imag(x[i]), imag(x[i]), imag(x[i]+1), imag(x[i]+1) } + MOVUPS (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0xB1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + + ADDPS X3, SUM // SUM += X_i + + ADDQ $2, IDX // IDX += 2 + DECQ LEN + JNZ dotu_tail_two // } while --LEN > 0 + + ADDPS SUM, P_SUM // P_SUM = { P_SUM[1] + SUM[1], P_SUM[0] + SUM[0] } + XORPS SUM, SUM // SUM = 0 + + ANDQ $1, TAIL + JZ dotu_end + +dotu_tail_one: + MOVSD (X_PTR)(IDX*8), 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]) } + MOVSD (Y_PTR)(IDX*8), X10 // X_j = { imag(y[i]), real(y[i]) } + MULPS X10, X3 // X_i = { imag(y[i]) * real(x[i]), real(y[i]) * real(x[i]) } + SHUFPS $0x1, X10, X10 // X_j = { real(y[i]), imag(y[i]) } + MULPS X10, X2 // X_(i-1) = { real(y[i]) * imag(x[i]), imag(y[i]) * imag(x[i]) } + + // X_i = { + // imag(result[i]): imag(y[i])*real(x[i]) + real(y[i])*imag(x[i]), + // real(result[i]): real(y[i])*real(x[i]) - imag(y[i])*imag(x[i]) } + ADDSUBPS_X2_X3 + + ADDPS X3, SUM // SUM += X_i + +dotu_end: + ADDPS P_SUM, SUM // SUM = { P_SUM[0] + SUM[0] } + MOVHLPS P_SUM, P_SUM // P_SUM = { P_SUM[1], P_SUM[1] } + ADDPS P_SUM, SUM // SUM = { P_SUM[1] + SUM[0] } + +dotu_ret: + MOVSD SUM, sum+48(FP) // return SUM + RET diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go new file mode 100644 index 00000000000..a84def87613 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/scal.go @@ -0,0 +1,79 @@ +// 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 + } +} + +// SscalUnitary is +// for i, v := range x { +// x[i] = complex(real(v)*alpha, imag(v)*alpha) +// } +func SscalUnitary(alpha float32, x []complex64) { + for i, v := range x { + x[i] = complex(real(v)*alpha, imag(v)*alpha) + } +} + +// SscalInc is +// var ix uintptr +// for i := 0; i < int(n); i++ { +// x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) +// ix += inc +// } +func SscalInc(alpha float32, x []complex64, n, inc uintptr) { + var ix uintptr + for i := 0; i < int(n); i++ { + x[ix] = complex(real(x[ix])*alpha, imag(x[ix])*alpha) + ix += inc + } +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.go new file mode 100644 index 00000000000..3e12d6bcd9a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_amd64.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. + +// +build !noasm,!appengine,!safe + +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) + +// DotcUnitary is +// for i, v := range x { +// sum += y[i] * conj(v) +// } +// return sum +func DotcUnitary(x, y []complex64) (sum complex64) + +// 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) + +// DotuUnitary is +// for i, v := range x { +// sum += y[i] * v +// } +// return sum +func DotuUnitary(x, y []complex64) (sum complex64) + +// 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) diff --git a/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.go new file mode 100644 index 00000000000..411afcb2a00 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/c64/stubs_noasm.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. + +// +build !amd64 noasm appengine safe + +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 + } +} + +// 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 +} + +// 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/vendor/gonum.org/v1/gonum/internal/asm/f64/BUILD b/vendor/gonum.org/v1/gonum/internal/asm/f64/BUILD index ac0be56094e..59361a98b9b 100644 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/BUILD +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/BUILD @@ -33,6 +33,7 @@ go_library( "scalunitaryto_amd64.s", "stubs_amd64.go", "stubs_noasm.go", + "sum_amd64.s", ], importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/internal/asm/f64", importpath = "gonum.org/v1/gonum/internal/asm/f64", diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go index 5a2c1d35c8e..2a1cfd5cdd0 100644 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/ge_noasm.go @@ -99,7 +99,7 @@ func GemvT(m, n uintptr, alpha float64, a []float64, lda uintptr, x []float64, i case int(incY) < 0: ScalInc(beta, y, n, uintptr(int(-incY))) case incY == 1: - ScalUnitary(beta, y) + ScalUnitary(beta, y[:n]) default: ScalInc(beta, y, n, incY) } diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s index 2abdddd832e..8d2a6a71a52 100644 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvN_amd64.s @@ -1,4 +1,4 @@ -// Copyright ©2017 The gonum Authors. All rights reserved. +// 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. diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s index 87ba5cbfccf..ff7d60fb68b 100644 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/gemvT_amd64.s @@ -1,4 +1,4 @@ -// Copyright ©2017 The gonum Authors. All rights reserved. +// 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. diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go index f6cf96ca4a2..a51b94514a5 100644 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_amd64.go @@ -163,3 +163,10 @@ func ScalInc(alpha float64, x []float64, n, incX uintptr) // idst += incDst // } func ScalIncTo(dst []float64, incDst uintptr, alpha float64, x []float64, n, incX uintptr) + +// Sum is +// var sum float64 +// for i := range x { +// sum += x[i] +// } +func Sum(x []float64) float64 diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go index eae620b1f15..670978aa47b 100644 --- a/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/stubs_noasm.go @@ -155,3 +155,16 @@ func LinfDist(s, t []float64) float64 { } return norm } + +// Sum is +// var sum float64 +// for i := range x { +// sum += x[i] +// } +func Sum(x []float64) float64 { + var sum float64 + for _, v := range x { + sum += v + } + return sum +} diff --git a/vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s b/vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s new file mode 100644 index 00000000000..22eede6e11a --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/asm/f64/sum_amd64.s @@ -0,0 +1,100 @@ +// Copyright ©2018 The Gonum 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,!safe + +#include "textflag.h" + +#define X_PTR SI +#define IDX AX +#define LEN CX +#define TAIL BX +#define SUM X0 +#define SUM_1 X1 +#define SUM_2 X2 +#define SUM_3 X3 + +// func Sum(x []float64) float64 +TEXT ·Sum(SB), NOSPLIT, $0 + MOVQ x_base+0(FP), X_PTR // X_PTR = &x + MOVQ x_len+8(FP), LEN // LEN = len(x) + XORQ IDX, IDX // i = 0 + PXOR SUM, SUM // p_sum_i = 0 + CMPQ LEN, $0 // if LEN == 0 { return 0 } + JE sum_end + + PXOR SUM_1, SUM_1 + PXOR SUM_2, SUM_2 + PXOR SUM_3, SUM_3 + + MOVQ X_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 + ADDSD (X_PTR), X0 // X0 += x[0] + INCQ IDX // i++ + DECQ LEN // LEN-- + DECQ TAIL // TAIL-- + JZ sum_end // if TAIL == 0 { return } + +no_trim: + MOVQ LEN, TAIL + SHRQ $4, LEN // LEN = floor( n / 16 ) + JZ sum_tail8 // if LEN == 0 { goto sum_tail8 } + +sum_loop: // sum 16x wide do { + ADDPD (SI)(AX*8), SUM // sum_i += x[i:i+2] + ADDPD 16(SI)(AX*8), SUM_1 + ADDPD 32(SI)(AX*8), SUM_2 + ADDPD 48(SI)(AX*8), SUM_3 + ADDPD 64(SI)(AX*8), SUM + ADDPD 80(SI)(AX*8), SUM_1 + ADDPD 96(SI)(AX*8), SUM_2 + ADDPD 112(SI)(AX*8), SUM_3 + ADDQ $16, IDX // i += 16 + DECQ LEN + JNZ sum_loop // } while --CX > 0 + +sum_tail8: + TESTQ $8, TAIL + JZ sum_tail4 + + ADDPD (SI)(AX*8), SUM // sum_i += x[i:i+2] + ADDPD 16(SI)(AX*8), SUM_1 + ADDPD 32(SI)(AX*8), SUM_2 + ADDPD 48(SI)(AX*8), SUM_3 + ADDQ $8, IDX + +sum_tail4: + ADDPD SUM_3, SUM + ADDPD SUM_2, SUM_1 + + TESTQ $4, TAIL + JZ sum_tail2 + + ADDPD (SI)(AX*8), SUM // sum_i += x[i:i+2] + ADDPD 16(SI)(AX*8), SUM_1 + ADDQ $4, IDX + +sum_tail2: + ADDPD SUM_1, SUM + + TESTQ $2, TAIL + JZ sum_tail1 + + ADDPD (SI)(AX*8), SUM // sum_i += x[i:i+2] + ADDQ $2, IDX + +sum_tail1: + HADDPD SUM, SUM // sum_i[0] += sum_i[1] + + TESTQ $1, TAIL + JZ sum_end + + ADDSD (SI)(IDX*8), SUM + +sum_end: // return sum + MOVSD SUM, sum+24(FP) + RET diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/BUILD b/vendor/gonum.org/v1/gonum/internal/cmplx64/BUILD new file mode 100644 index 00000000000..43ea882af9e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/BUILD @@ -0,0 +1,31 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "abs.go", + "conj.go", + "doc.go", + "isinf.go", + "isnan.go", + "sqrt.go", + ], + importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/internal/cmplx64", + importpath = "gonum.org/v1/gonum/internal/cmplx64", + visibility = ["//vendor/gonum.org/v1/gonum:__subpackages__"], + deps = ["//vendor/gonum.org/v1/gonum/internal/math32:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go new file mode 100644 index 00000000000..ac6eb81c0e2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/abs.go @@ -0,0 +1,14 @@ +// Copyright 2010 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 ©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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// Abs returns the absolute value (also called the modulus) of x. +func Abs(x complex64) float32 { return math.Hypot(real(x), imag(x)) } diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go new file mode 100644 index 00000000000..705262f2f93 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/conj.go @@ -0,0 +1,12 @@ +// Copyright 2010 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 ©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 cmplx64 + +// Conj returns the complex conjugate of x. +func Conj(x complex64) complex64 { return complex(real(x), -imag(x)) } diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go new file mode 100644 index 00000000000..5424ea099c2 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/doc.go @@ -0,0 +1,7 @@ +// 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 cmplx64 provides complex64 versions of standard library math/cmplx +// package routines used by gonum/blas. +package cmplx64 // import "gonum.org/v1/gonum/internal/cmplx64" diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go new file mode 100644 index 00000000000..21d3d180e1e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/isinf.go @@ -0,0 +1,25 @@ +// Copyright 2010 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 ©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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// IsInf returns true if either real(x) or imag(x) is an infinity. +func IsInf(x complex64) bool { + if math.IsInf(real(x), 0) || math.IsInf(imag(x), 0) { + return true + } + return false +} + +// Inf returns a complex infinity, complex(+Inf, +Inf). +func Inf() complex64 { + inf := math.Inf(1) + return complex(inf, inf) +} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go new file mode 100644 index 00000000000..7e0bf788f1e --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/isnan.go @@ -0,0 +1,29 @@ +// Copyright 2010 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 ©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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// IsNaN returns true if either real(x) or imag(x) is NaN +// and neither is an infinity. +func IsNaN(x complex64) bool { + switch { + case math.IsInf(real(x), 0) || math.IsInf(imag(x), 0): + return false + case math.IsNaN(real(x)) || math.IsNaN(imag(x)): + return true + } + return false +} + +// NaN returns a complex ``not-a-number'' value. +func NaN() complex64 { + nan := math.NaN() + return complex(nan, nan) +} diff --git a/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go b/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go new file mode 100644 index 00000000000..439987b4baa --- /dev/null +++ b/vendor/gonum.org/v1/gonum/internal/cmplx64/sqrt.go @@ -0,0 +1,108 @@ +// Copyright 2010 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 ©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 cmplx64 + +import math "gonum.org/v1/gonum/internal/math32" + +// The original C code, the long comment, and the constants +// below are from http://netlib.sandia.gov/cephes/c9x-complex/clog.c. +// The go code is a simplified version of the original C. +// +// Cephes Math Library Release 2.8: June, 2000 +// Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier +// +// The readme file at http://netlib.sandia.gov/cephes/ says: +// Some software in this archive may be from the book _Methods and +// Programs for Mathematical Functions_ (Prentice-Hall or Simon & Schuster +// International, 1989) or from the Cephes Mathematical Library, a +// commercial product. In either event, it is copyrighted by the author. +// What you see here may be used freely but it comes with no support or +// guarantee. +// +// The two known misprints in the book are repaired here in the +// source listings for the gamma function and the incomplete beta +// integral. +// +// Stephen L. Moshier +// moshier@na-net.ornl.gov + +// Complex square root +// +// DESCRIPTION: +// +// If z = x + iy, r = |z|, then +// +// 1/2 +// Re w = [ (r + x)/2 ] , +// +// 1/2 +// Im w = [ (r - x)/2 ] . +// +// Cancelation error in r-x or r+x is avoided by using the +// identity 2 Re w Im w = y. +// +// Note that -w is also a square root of z. The root chosen +// is always in the right half plane and Im w has the same sign as y. +// +// ACCURACY: +// +// Relative error: +// arithmetic domain # trials peak rms +// DEC -10,+10 25000 3.2e-17 9.6e-18 +// IEEE -10,+10 1,000,000 2.9e-16 6.1e-17 + +// Sqrt returns the square root of x. +// The result r is chosen so that real(r) ≥ 0 and imag(r) has the same sign as imag(x). +func Sqrt(x complex64) complex64 { + if imag(x) == 0 { + if real(x) == 0 { + return complex(0, 0) + } + if real(x) < 0 { + return complex(0, math.Sqrt(-real(x))) + } + return complex(math.Sqrt(real(x)), 0) + } + if real(x) == 0 { + if imag(x) < 0 { + r := math.Sqrt(-0.5 * imag(x)) + return complex(r, -r) + } + r := math.Sqrt(0.5 * imag(x)) + return complex(r, r) + } + a := real(x) + b := imag(x) + var scale float32 + // Rescale to avoid internal overflow or underflow. + if math.Abs(a) > 4 || math.Abs(b) > 4 { + a *= 0.25 + b *= 0.25 + scale = 2 + } else { + a *= 1.8014398509481984e16 // 2**54 + b *= 1.8014398509481984e16 + scale = 7.450580596923828125e-9 // 2**-27 + } + r := math.Hypot(a, b) + var t float32 + if a > 0 { + t = math.Sqrt(0.5*r + 0.5*a) + r = scale * math.Abs((0.5*b)/t) + t *= scale + } else { + r = math.Sqrt(0.5*r - 0.5*a) + t = scale * math.Abs((0.5*b)/r) + r *= scale + } + if b < 0 { + return complex(t, -r) + } + return complex(t, r) +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/BUILD b/vendor/gonum.org/v1/gonum/lapack/gonum/BUILD index 7ae72210ccd..6504605fec9 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/BUILD +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/BUILD @@ -76,6 +76,8 @@ go_library( "dlasy2.go", "dlatrd.go", "dlatrs.go", + "dlauu2.go", + "dlauum.go", "doc.go", "dorg2l.go", "dorg2r.go", @@ -97,6 +99,8 @@ go_library( "dpocon.go", "dpotf2.go", "dpotrf.go", + "dpotri.go", + "dpotrs.go", "drscl.go", "dsteqr.go", "dsterf.go", @@ -110,11 +114,12 @@ go_library( "dtrti2.go", "dtrtri.go", "dtrtrs.go", - "general.go", + "errors.go", "iladlc.go", "iladlr.go", "ilaenv.go", "iparmq.go", + "lapack.go", ], importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/lapack/gonum", importpath = "gonum.org/v1/gonum/lapack/gonum", diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go index dd6e8b3a43b..5f3833fd97a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dbdsqr.go @@ -50,35 +50,53 @@ import ( // // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case ncvt < 0: + panic(ncvtLT0) + case nru < 0: + panic(nruLT0) + case ncc < 0: + panic(nccLT0) + case ldvt < max(1, ncvt): + panic(badLdVT) + case (ldu < max(1, n) && nru > 0) || (ldu < 1 && nru == 0): + panic(badLdU) + case ldc < max(1, ncc): + panic(badLdC) } - 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-1) { - panic(badWork) - } - var info int - bi := blas64.Implementation() - const ( - maxIter = 6 - ) + + // Quick return if possible. if n == 0 { return true } + + if len(vt) < (n-1)*ldvt+ncvt && ncvt != 0 { + panic(shortVT) + } + if len(u) < (nru-1)*ldu+n && nru != 0 { + panic(shortU) + } + if len(c) < (n-1)*ldc+ncc && ncc != 0 { + panic(shortC) + } + if len(d) < n { + panic(shortD) + } + if len(e) < n-1 { + panic(shortE) + } + if len(work) < 4*(n-1) { + panic(shortWork) + } + + var info int + bi := blas64.Implementation() + const maxIter = 6 + if n != 1 { // If the singular vectors do not need to be computed, use qd algorithm. if !(ncvt > 0 || nru > 0 || ncc > 0) { @@ -87,7 +105,6 @@ func (impl Implementation) Dbdsqr(uplo blas.Uplo, n, ncvt, nru, ncc int, d, e, v if info != 2 { return info == 0 } - info = 0 } nm1 := n - 1 nm12 := nm1 + nm1 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go index fa9f1eaba4b..7caa0b17391 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebak.go @@ -10,8 +10,8 @@ import ( ) // 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, +// V = P D V, if side == lapack.EVRight, +// V = P D^{-1} V, if side == lapack.EVLeft, // where P and D are n×n permutation and scaling matrices, respectively, // implicitly represented by job, scale, ilo and ihi as returned by Dgebal. // @@ -20,34 +20,45 @@ import ( // 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(badEVSide) - case lapack.LeftEV, lapack.RightEV: - } - checkMatrix(n, m, v, ldv) +func (impl Implementation) Dgebak(job lapack.BalanceJob, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) { switch { + case job != lapack.BalanceNone && job != lapack.Permute && job != lapack.Scale && job != lapack.PermuteScale: + panic(badBalanceJob) + case side != lapack.EVLeft && side != lapack.EVRight: + panic(badEVSide) + 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 m < 0: + panic(mLT0) + case ldv < max(1, m): + panic(badLdV) } // Quick return if possible. - if n == 0 || m == 0 || job == lapack.None { + if n == 0 || m == 0 { + return + } + + if len(scale) < n { + panic(shortScale) + } + if len(v) < (n-1)*ldv+m { + panic(shortV) + } + + // Quick return if possible. + if job == lapack.BalanceNone { return } bi := blas64.Implementation() if ilo != ihi && job != lapack.Permute { // Backward balance. - if side == lapack.RightEV { + if side == lapack.EVRight { for i := ilo; i <= ihi; i++ { bi.Dscal(m, scale[i], v[i*ldv:], 1) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go index 4af7eed2adc..6fb5170cd28 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebal.go @@ -35,14 +35,14 @@ import ( // 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.BalanceNone, 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 +// If job is lapack.BalanceNone 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 @@ -54,27 +54,38 @@ import ( // 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") +func (impl Implementation) Dgebal(job lapack.BalanceJob, n int, a []float64, lda int, scale []float64) (ilo, ihi int) { + switch { + case job != lapack.BalanceNone && job != lapack.Permute && job != lapack.Scale && job != lapack.PermuteScale: + panic(badBalanceJob) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } ilo = 0 ihi = n - 1 - if n == 0 || job == lapack.None { + if n == 0 { + return ilo, ihi + } + + if len(scale) != n { + panic(shortScale) + } + + if job == lapack.BalanceNone { for i := range scale { scale[i] = 1 } return ilo, ihi } + if len(a) < (n-1)*lda+n { + panic(shortA) + } + bi := blas64.Implementation() swapped := true diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go index a8e4aacbc92..cf951a1202f 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebd2.go @@ -15,22 +15,34 @@ import "gonum.org/v1/gonum/blas" // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - if len(e) < min(m, n)-1 { - panic(badE) + + // Quick return if possible. + minmn := min(m, n) + if minmn == 0 { + return } - if len(tauQ) < min(m, n) { - panic(badTauQ) - } - if len(tauP) < min(m, n) { - panic(badTauP) - } - if len(work) < max(m, n) { - panic(badWork) + + switch { + case len(d) < minmn: + panic(shortD) + case len(e) < minmn-1: + panic(shortE) + case len(tauQ) < minmn: + panic(shortTauQ) + case len(tauP) < minmn: + panic(shortTauP) + case len(work) < max(m, n): + panic(shortWork) } + 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) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go index 794ac2c0eee..f03bf8d939f 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgebrd.go @@ -53,46 +53,62 @@ import ( // // 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)) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, max(m, n)) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + // Quick return if possible. + minmn := min(m, n) + if minmn == 0 { + work[0] = 1 return } - minmn := min(m, n) - if len(d) < minmn { - panic(badD) + + nb := impl.Ilaenv(1, "DGEBRD", " ", m, n, -1, -1) + lwkopt := (m + n) * nb + if lwork == -1 { + work[0] = float64(lwkopt) + return } - if len(e) < minmn-1 { - panic(badE) - } - if len(tauQ) < minmn { - panic(badTauQ) - } - if len(tauP) < minmn { - panic(badTauP) + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(d) < minmn: + panic(shortD) + case len(e) < minmn-1: + panic(shortE) + case len(tauQ) < minmn: + panic(shortTauQ) + case len(tauP) < minmn: + panic(shortTauP) } + + nx := minmn 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 { + if 1 < nb && nb < minmn { + // At least one blocked operation can be done. + // Get the crossover point nx. nx = max(nb, impl.Ilaenv(3, "DGEBRD", " ", m, n, -1, -1)) + // Determine when to switch from blocked to unblocked code. if nx < minmn { + // At least one blocked operation will be done. ws = (m + n) * nb if lwork < ws { + // Not enough work space for the optimal nb, + // consider using a smaller block size. nbmin := impl.Ilaenv(2, "DGEBRD", " ", m, n, -1, -1) if lwork >= (m+n)*nbmin { + // Enough work space for minimum block size. nb = lwork / (m + n) } else { nb = minmn @@ -100,17 +116,12 @@ func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, ta } } } - } 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 { + for i = 0; i < minmn-nx; 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. @@ -146,5 +157,5 @@ func (impl Implementation) Dgebrd(m, n int, a []float64, lda int, d, e, tauQ, ta } // 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) + work[0] = float64(ws) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go index 04e01535fe4..1d1ca586bb5 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgecon.go @@ -24,20 +24,31 @@ import ( // // 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 { + switch { + case norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum: panic(badNorm) - } - if len(work) < 4*n { - panic(badWork) - } - if len(iwork) < n { - panic(badWork) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } + // Quick return if possible. if n == 0 { return 1 - } else if anorm == 0 { + } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(work) < 4*n: + panic(shortWork) + case len(iwork) < n: + panic(shortIWork) + } + + // Quick return if possible. + if anorm == 0 { return 0 } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go index 314074c9591..0da4e609c55 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeev.go @@ -36,9 +36,10 @@ import ( // 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. +// Left eigenvectors will be computed only if jobvl == lapack.LeftEVCompute, +// otherwise jobvl must be lapack.LeftEVNone. +// Right eigenvectors will be computed only if jobvr == lapack.RightEVCompute, +// otherwise jobvr must be lapack.RightEVNone. // For other values of jobvl and jobvr Dgeev will panic. // // wr and wi contain the real and imaginary parts, respectively, of the computed @@ -60,50 +61,31 @@ import ( // 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) - } + wantvl := jobvl == lapack.LeftEVCompute + wantvr := jobvr == lapack.RightEVCompute 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) - } + switch { + case jobvl != lapack.LeftEVCompute && jobvl != lapack.LeftEVNone: + panic(badLeftEVJob) + case jobvr != lapack.RightEVCompute && jobvr != lapack.RightEVNone: + panic(badRightEVJob) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case ldvl < 1 || (ldvl < n && wantvl): + panic(badLdVL) + case ldvr < 1 || (ldvr < n && wantvr): + panic(badLdVR) + case lwork < minwrk && lwork != -1: + panic(badLWork) + case len(work) < lwork: + panic(shortWork) } // Quick return if possible. @@ -115,20 +97,20 @@ func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob 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) + impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.SchurOrig, n, 0, n-1, + a, lda, wr, wi, nil, n, work, -1) maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) - side := lapack.LeftEV + side := lapack.EVLeft if wantvr { - side = lapack.RightEV + side = lapack.EVRight } - impl.Dtrevc3(side, lapack.AllEVMulQ, nil, n, nil, 1, nil, 1, nil, 1, + impl.Dtrevc3(side, lapack.EVAllMulQ, nil, n, a, lda, vl, ldvl, vr, ldvr, 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) + impl.Dhseqr(lapack.EigenvaluesOnly, lapack.SchurNone, n, 0, n-1, + a, lda, wr, wi, vr, ldvr, work, -1) maxwrk = max(maxwrk, max(n+1, n+int(work[0]))) } maxwrk = max(maxwrk, minwrk) @@ -138,6 +120,19 @@ func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob return 0 } + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(wr) != n: + panic(badLenWr) + case len(wi) != n: + panic(badLenWi) + case len(vl) < (n-1)*ldvl+n && wantvl: + panic(shortVL) + case len(vr) < (n-1)*ldvr+n && wantvr: + panic(shortVR) + } + // Get machine constants. smlnum := math.Sqrt(dlamchS) / dlamchP bignum := 1 / smlnum @@ -168,35 +163,35 @@ func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob var side lapack.EVSide if wantvl { - side = lapack.LeftEV + side = lapack.EVLeft // 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, + first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.SchurOrig, 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 + side = lapack.EVBoth impl.Dlacpy(blas.All, n, n, vl, ldvl, vr, ldvr) } } else if wantvr { - side = lapack.RightEV + side = lapack.EVRight // 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, + first = impl.Dhseqr(lapack.EigenvaluesAndSchur, lapack.SchurOrig, 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, + first = impl.Dhseqr(lapack.EigenvaluesOnly, lapack.SchurNone, n, ilo, ihi, a, lda, wr, wi, nil, 1, work[iwrk:], lwork-iwrk) } @@ -214,13 +209,13 @@ func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob if wantvl || wantvr { // Compute left and/or right eigenvectors. - impl.Dtrevc3(side, lapack.AllEVMulQ, nil, n, + impl.Dtrevc3(side, lapack.EVAllMulQ, 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) + impl.Dgebak(lapack.PermuteScale, lapack.EVLeft, n, ilo, ihi, workbal, n, vl, ldvl) // Normalize left eigenvectors and make largest component real. for i, wii := range wi { if wii < 0 { @@ -247,7 +242,7 @@ func (impl Implementation) Dgeev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob } if wantvr { // Undo balancing of right eigenvectors. - impl.Dgebak(lapack.PermuteScale, lapack.RightEV, n, ilo, ihi, workbal, n, vr, ldvr) + impl.Dgebak(lapack.PermuteScale, lapack.EVRight, n, ilo, ihi, workbal, n, vr, ldvr) // Normalize right eigenvectors and make largest component real. for i, wii := range wi { if wii < 0 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go index 3682837889d..261f21b983a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehd2.go @@ -56,16 +56,29 @@ import "gonum.org/v1/gonum/blas" // // 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): + case n < 0: + panic(nLT0) + case ilo < 0 || max(0, n-1) < ilo: panic(badIlo) - case ihi < min(ilo, n-1) || ihi >= n: + case ihi < min(ilo, n-1) || n <= ihi: panic(badIhi) + case lda < max(1, n): + panic(badLdA) + } + + // Quick return if possible. + if n == 0 { + return + } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) case len(tau) != n-1: - panic(badTau) + panic(badLenTau) case len(work) < n: - panic(badWork) + panic(shortWork) } for i := ilo; i < ihi; i++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go index 027747d1ddb..89b73cef991 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgehrd.go @@ -67,20 +67,24 @@ import ( // 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 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 lda < max(1, n): + panic(badLdA) case lwork < max(1, n) && lwork != -1: - panic(badWork) + panic(badLWork) case len(work) < lwork: panic(shortWork) } - if lwork != -1 { - checkMatrix(n, n, a, lda) - if len(tau) != n-1 && n > 0 { - panic(badTau) - } + + // Quick return if possible. + if n == 0 { + work[0] = 1 + return } const ( @@ -96,6 +100,13 @@ func (impl Implementation) Dgehrd(n, ilo, ihi int, a []float64, lda int, tau, wo return } + if len(a) < (n-1)*lda+n { + panic(shortA) + } + if len(tau) != n-1 { + panic(badLenTau) + } + // Set tau[:ilo] and tau[ihi:] to zero. for i := 0; i < ilo; i++ { tau[i] = 0 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go index 05b3ce45b6c..abc96f7d2a9 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelq2.go @@ -25,14 +25,30 @@ import "gonum.org/v1/gonum/blas" // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + } + + // Quick return if possible. k := min(m, n) - if len(tau) < k { - panic(badTau) + if k == 0 { + return } - if len(work) < m { - panic(badWork) + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(work) < m: + panic(shortWork) } + 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 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go index 12913911b35..f1fd13a0196 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgelqf.go @@ -21,33 +21,44 @@ import ( // // 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 { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, m) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): panic(shortWork) } - if lwork < m { - panic(badWork) - } + k := min(m, n) - if len(tau) < k { - panic(badTau) - } if k == 0 { + work[0] = 1 return } + + nb := impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) + if lwork == -1 { + work[0] = float64(m * nb) + return + } + + if len(a) < (m-1)*lda+n { + panic(shortA) + } + if len(tau) < k { + panic(shortTau) + } + // 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 { + if 1 < nb && nb < k { nx = max(0, impl.Ilaenv(3, "DGELQF", " ", m, n, -1, -1)) if nx < k { iws = m * nb @@ -57,9 +68,10 @@ func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []fl } } } + ldwork := nb // Computed blocked LQ factorization. var i int - if nb >= nbmin && nb < k && nx < k { + if nbmin <= nb && 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) @@ -81,4 +93,5 @@ func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []fl if i < k { impl.Dgelq2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) } + work[0] = float64(iws) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go index 214b966303f..a3894b6a0b6 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgels.go @@ -39,46 +39,63 @@ import ( // 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) + minwrk := mn + max(mn, nrhs) + switch { + case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: + panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case nrhs < 0: + panic(nrhsLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, nrhs): + panic(badLdB) + case lwork < max(1, minwrk) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + // Quick return if possible. + if mn == 0 || nrhs == 0 { + impl.Dlaset(blas.All, max(m, n), nrhs, 0, 0, b, ldb) + work[0] = 1 + return true + } // 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 { + if trans != blas.NoTrans { 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 { + if trans != blas.NoTrans { 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)) } } + wsize := max(1, mn+max(mn, nrhs)*nb) + work[0] = float64(wsize) + 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 + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(b) < (max(m, n)-1)*ldb+nrhs: + panic(shortB) } // Scale the input matrices if they contain extreme values. @@ -97,7 +114,7 @@ func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float return true } brow := m - if tpsd { + if trans != blas.NoTrans { brow = n } bnrm := impl.Dlange(lapack.MaxAbs, brow, nrhs, b, ldb, nil) @@ -114,7 +131,7 @@ func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float var scllen int if m >= n { impl.Dgeqrf(m, n, a, lda, work, work[mn:], lwork-mn) - if !tpsd { + if trans == blas.NoTrans { impl.Dormqr(blas.Left, blas.Trans, m, nrhs, n, a, lda, work[:n], @@ -148,7 +165,7 @@ func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float } } else { impl.Dgelqf(m, n, a, lda, work, work[mn:], lwork-mn) - if !tpsd { + if trans == blas.NoTrans { ok := impl.Dtrtrs(blas.Lower, blas.NoTrans, blas.NonUnit, m, nrhs, a, lda, @@ -196,5 +213,7 @@ func (impl Implementation) Dgels(trans blas.Transpose, m, n, nrhs int, a []float if ibscl == 2 { impl.Dlascl(lapack.General, 0, 0, bignum, bnrm, scllen, nrhs, b, ldb) } + + work[0] = float64(wsize) return true } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go index 6d9b7413f01..3f3ddb163fd 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeql2.go @@ -24,14 +24,30 @@ import "gonum.org/v1/gonum/blas" // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } + + // Quick return if possible. k := min(m, n) + if k == 0 { + return + } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(work) < n: + panic(shortWork) + } + 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]. diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go index ef71b3ad269..6949da967a2 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqp3.go @@ -45,38 +45,50 @@ func (impl Implementation) Dgeqp3(m, n int, a []float64, lda int, jpvt []int, ta 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 + iws := 3*n + 1 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < iws && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) + } - if lwork == -1 { + // Quick return if possible. + if minmn == 0 { + work[0] = 1 return } - if len(tau) < minmn { - panic(badTau) + nb := impl.Ilaenv(inb, "DGEQRF", " ", m, n, -1, -1) + if lwork == -1 { + work[0] = float64(2*n + (n+1)*nb) + return + } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(jpvt) != n: + panic(badLenJpvt) + case len(tau) < minmn: + panic(shortTau) + } + + for _, v := range jpvt { + if v < -1 || n <= v { + panic(badJpvt) + } } bi := blas64.Implementation() diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go index 05df4265396..3e35d7e2f42 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqr2.go @@ -34,14 +34,31 @@ func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []fl // 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) + + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case len(work) < n: + panic(shortWork) } + + // Quick return if possible. k := min(m, n) - if len(tau) < k { - panic(badTau) + if k == 0 { + return } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + } + 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) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go index a8a8155a867..300f8eea4e0 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgeqrf.go @@ -22,32 +22,43 @@ import ( // // 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) { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, n) && lwork != -1: + panic(badLWork) + case 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 := max(1, n*nb) - if lwork == -1 { - work[0] = float64(lworkopt) - return - } - checkMatrix(m, n, a, lda) - if lwork < n { - panic(badWork) - } + + // Quick return if possible. k := min(m, n) - if len(tau) < k { - panic(badTau) - } if k == 0 { work[0] = 1 return } + + // nb is the optimal blocksize, i.e. the number of columns transformed at a time. + nb := impl.Ilaenv(1, "DGEQRF", " ", m, n, -1, -1) + if lwork == -1 { + work[0] = float64(n * nb) + return + } + + if len(a) < (m-1)*lda+n { + panic(shortA) + } + if len(tau) < k { + panic(shortTau) + } + 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 { @@ -55,7 +66,7 @@ func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []fl // to unblocked. nx = max(0, impl.Ilaenv(3, "DGEQRF", " ", m, n, -1, -1)) if k > nx { - iws = ldwork * n + iws = n * nb if lwork < iws { // Not enough workspace to use the optimal block // size. Get the minimum block size instead. @@ -64,12 +75,11 @@ func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []fl } } } - for i := range work { - work[i] = 0 - } + // Compute QR using a blocked algorithm. var i int if nbmin <= nb && nb < k && nx < k { + ldwork := nb for i = 0; i < k-nx; i += nb { ib := min(k-i, nb) // Compute the QR factorization of the current block. @@ -94,5 +104,5 @@ func (impl Implementation) Dgeqrf(m, n int, a []float64, lda int, tau, work []fl if i < k { impl.Dgeqr2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) } - work[0] = float64(lworkopt) + work[0] = float64(iws) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go index 52ac2cb8ef1..60dac973a14 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerq2.go @@ -28,13 +28,28 @@ import "gonum.org/v1/gonum/blas" // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case len(work) < m: + panic(shortWork) } - if len(work) < m { - panic(badWork) + + // Quick return if possible. + k := min(m, n) + if k == 0 { + return + } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) } for i := k - 1; i >= 0; i-- { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go index 7ecdf55f32d..9b4aa050efb 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgerqf.go @@ -32,36 +32,37 @@ import ( // // 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) { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, m) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): panic(shortWork) } - if lwork != -1 && lwork < max(1, m) { - panic(badWork) - } + // Quick return if possible. 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] = 1 + return } - work[0] = float64(lwkopt) + nb := impl.Ilaenv(1, "DGERQF", " ", m, n, -1, -1) if lwork == -1 { + work[0] = float64(m * nb) return } - // Return quickly if possible. - if k == 0 { - return + if len(a) < (m-1)*lda+n { + panic(shortA) + } + if len(tau) != k { + panic(badLenTau) } nbmin := 2 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go index 70f6db8909a..136f683e4b9 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgesvd.go @@ -26,7 +26,7 @@ const noSVDO = "dgesvd: not coded for overwrite" // 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.SVDStore 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 @@ -40,12 +40,12 @@ const noSVDO = "dgesvd: not coded for overwrite" // 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 +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDStore 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 +// jobV == lapack.SVDAll, vt is of size n×n. If jobVT == lapack.SVDStore vt is // of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is // not used. // @@ -57,70 +57,87 @@ const noSVDO = "dgesvd: not coded for overwrite" // // 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 { + + wantua := jobU == lapack.SVDAll + wantus := jobU == lapack.SVDStore + wantuas := wantua || wantus + wantuo := jobU == lapack.SVDOverwrite + wantun := jobU == lapack.SVDNone + if !(wantua || wantus || wantuo || wantun) { + panic(badSVDJob) + } + + wantva := jobVT == lapack.SVDAll + wantvs := jobVT == lapack.SVDStore + wantvas := wantva || wantvs + wantvo := jobVT == lapack.SVDOverwrite + wantvn := jobVT == lapack.SVDNone + if !(wantva || wantvs || wantvo || wantvn) { + panic(badSVDJob) + } + + if wantuo && wantvo { + panic(bothSVDOver) + } + + minmn := min(m, n) + minwork := 1 + if minmn > 0 { + minwork = max(3*minmn+max(m, n), 5*minmn) + } + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case ldu < 1, wantua && ldu < m, wantus && ldu < minmn: + panic(badLdU) + case ldvt < 1 || (wantvas && ldvt < n): + panic(badLdVT) + case lwork < minwork && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + // Quick return if possible. + if minmn == 0 { + work[0] = 1 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 + // Compute optimal workspace size for subroutines. opts := string(jobU) + string(jobVT) + mnthr := impl.Ilaenv(6, "DGESVD", opts, m, n, 0, 0) + maxwrk := 1 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) + + impl.Dorgbr(lapack.GeneratePT, 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) + + impl.Dorgbr(lapack.GenerateQ, n, n, n, a, lda, nil, work, -1) lwork_dorgbr_q := int(work[0]) if m >= mnthr { - // m >> n if wantun { - // Path 1 + // Path 1 (m much larger than n, jobU == None) maxwrk = n + lwork_dgeqrf maxwrk = max(maxwrk, 3*n+lwork_dgebrd) if wantvo || wantvas { @@ -128,15 +145,15 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float } maxwrk = max(maxwrk, bdspac) } else if wantuo && wantvn { - // Path 2 + // Path 2 (m much larger than n, jobU == Overwrite, jobVT == None) 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 + } else if wantuo && wantvas { + // Path 3 (m much larger than n, jobU == Overwrite, jobVT == Store or All) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_n) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -145,7 +162,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = max(n*n+wrkbl, n*n+m*n+n) } else if wantus && wantvn { - // Path 4 + // Path 4 (m much larger than n, jobU == Store, jobVT == None) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_n) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -153,7 +170,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = n*n + wrkbl } else if wantus && wantvo { - // Path 5 + // Path 5 (m much larger than n, jobU == Store, jobVT == Overwrite) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_n) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -162,7 +179,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = 2*n*n + wrkbl } else if wantus && wantvas { - // Path 6 + // Path 6 (m much larger than n, jobU == Store, jobVT == Store or All) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_n) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -171,7 +188,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = n*n + wrkbl } else if wantua && wantvn { - // Path 7 + // Path 7 (m much larger than n, jobU == All, jobVT == None) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_m) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -179,7 +196,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = n*n + wrkbl } else if wantua && wantvo { - // Path 8 + // Path 8 (m much larger than n, jobU == All, jobVT == Overwrite) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_m) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -188,7 +205,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = 2*n*n + wrkbl } else if wantua && wantvas { - // Path 9 + // Path 9 (m much larger than n, jobU == All, jobVT == Store or All) wrkbl = n + lwork_dgeqrf wrkbl = max(wrkbl, n+lwork_dorgqr_m) wrkbl = max(wrkbl, 3*n+lwork_dgebrd) @@ -198,17 +215,17 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float maxwrk = n*n + wrkbl } } else { - // Path 10: m > n + // Path 10 (m at least n, but not much larger) 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) + impl.Dorgbr(lapack.GenerateQ, 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) + impl.Dorgbr(lapack.GenerateQ, m, m, n, a, lda, nil, work, -1) lwork_dorgbr_q := int(work[0]) maxwrk = max(maxwrk, 3*n+lwork_dorgbr_q) } @@ -218,25 +235,28 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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) + + impl.Dorgbr(lapack.GeneratePT, 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) + + impl.Dorgbr(lapack.GenerateQ, m, m, m, a, n, nil, work, -1) lwork_dorgbr_q := int(work[0]) + if n >= mnthr { - // n >> m if wantvn { - // Path 1t + // Path 1t (n much larger than m, jobVT == None) maxwrk = m + lwork_dgelqf maxwrk = max(maxwrk, 3*m+lwork_dgebrd) if wantuo || wantuas { @@ -244,7 +264,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float } maxwrk = max(maxwrk, bdspac) } else if wantvo && wantun { - // Path 2t + // Path 2t (n much larger than m, jobU == None, jobVT == Overwrite) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_m) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -252,7 +272,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = max(m*m+wrkbl, m*m+m*n+m) } else if wantvo && wantuas { - // Path 3t + // Path 3t (n much larger than m, jobU == Store or All, jobVT == Overwrite) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_m) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -261,7 +281,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = max(m*m+wrkbl, m*m+m*n+m) } else if wantvs && wantun { - // Path 4t + // Path 4t (n much larger than m, jobU == None, jobVT == Store) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_m) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -269,7 +289,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = m*m + wrkbl } else if wantvs && wantuo { - // Path 5t + // Path 5t (n much larger than m, jobU == Overwrite, jobVT == Store) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_m) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -278,7 +298,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = 2*m*m + wrkbl } else if wantvs && wantuas { - // Path 6t + // Path 6t (n much larger than m, jobU == Store or All, jobVT == Store) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_m) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -287,7 +307,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = m*m + wrkbl } else if wantva && wantun { - // Path 7t + // Path 7t (n much larger than m, jobU== None, jobVT == All) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_n) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -295,7 +315,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = m*m + wrkbl } else if wantva && wantuo { - // Path 8t + // Path 8t (n much larger than m, jobU == Overwrite, jobVT == All) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_n) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -304,7 +324,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float wrkbl = max(wrkbl, bdspac) maxwrk = 2*m*m + wrkbl } else if wantva && wantuas { - // Path 9t + // Path 9t (n much larger than m, jobU == Store or All, jobVT == All) wrkbl = m + lwork_dgelqf wrkbl = max(wrkbl, m+lwork_dorglq_n) wrkbl = max(wrkbl, 3*m+lwork_dgebrd) @@ -314,17 +334,17 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float maxwrk = m*m + wrkbl } } else { - // Path 10t, n > m + // Path 10t (n greater than m, but not much larger) 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) + impl.Dorgbr(lapack.GeneratePT, 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) + impl.Dorgbr(lapack.GeneratePT, n, n, m, a, n, nil, work, -1) lwork_dorgbr_p = int(work[0]) maxwrk = max(maxwrk, 3*m+lwork_dorgbr_p) } @@ -335,29 +355,25 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float } } - 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) + maxwrk = max(maxwrk, minwork) if lwork == -1 { + work[0] = float64(maxwrk) return true } + if len(a) < (m-1)*lda+n { + panic(shortA) + } + if len(s) < minmn { + panic(shortS) + } + if (len(u) < (m-1)*ldu+m && wantua) || (len(u) < (m-1)*ldu+minmn && wantus) { + panic(shortU) + } + if (len(vt) < (n-1)*ldvt+n && wantva) || (len(vt) < (minmn-1)*ldvt+n && wantvs) { + panic(shortVT) + } + // Perform decomposition. eps := dlamchE smlnum := math.Sqrt(dlamchS) / eps @@ -374,6 +390,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float impl.Dlascl(lapack.General, 0, 0, anrm, bignum, m, n, a, lda) } + bi := blas64.Implementation() var ie int if m >= n { // If A has sufficiently more rows than columns, use the QR decomposition. @@ -398,8 +415,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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:], + impl.Dorgbr(lapack.GeneratePT, n, n, n, a, lda, work[itaup:], work[iwork:], lwork-iwork) ncvt = n } @@ -453,7 +469,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GenerateQ, n, n, n, work[ir:], ldworkr, work[itauq:], work[iwork:], lwork-iwork) iwork = ie + n @@ -536,11 +552,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GenerateQ, 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, + impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) iwork = ie + n @@ -584,7 +600,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) iwork = ie + n @@ -630,7 +646,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GenerateQ, n, n, n, work[ir:], ldworkr, work[itauq:], work[iwork:], lwork-iwork) iwork = ie + n @@ -718,11 +734,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GenerateQ, 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, + impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) iwork = ie + n @@ -750,7 +766,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) iwork = ie + n @@ -774,7 +790,9 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float // 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) + if n > 1 { + impl.Dlaset(blas.Lower, n-1, n-1, 0, 0, vt[ldvt:], ldvt) + } ie := itau itauq := ie + n @@ -790,14 +808,14 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, 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:], + ok = impl.Dbdsqr(blas.Upper, n, n, m, 0, s, work[ie:], vt, ldvt, u, ldu, work, 1, work[iwork:]) } } @@ -824,13 +842,13 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float if wantua { ncu = m } - impl.Dorgbr(lapack.ApplyQ, m, ncu, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) + impl.Dorgbr(lapack.GenerateQ, 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) + impl.Dorgbr(lapack.GeneratePT, n, n, n, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) } if wantuo { panic(noSVDO) @@ -886,7 +904,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GenerateQ, m, m, m, a, lda, work[itauq:], work[iwork:], lwork-iwork) } iwork = ie + m @@ -944,7 +962,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, m, m, m, work[ir:], ldworkr, work[itaup:], work[iwork:], lwork-iwork) iwork = ie + m @@ -1029,11 +1047,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, 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) + impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) iwork = ie + m // Perform bidiagonal QR iteration, computing left singular @@ -1076,13 +1094,13 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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) + impl.Dorgbr(lapack.GenerateQ, 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, + ok = impl.Dbdsqr(blas.Upper, m, n, m, 0, s, work[ie:], vt, ldvt, u, ldu, work, 1, work[iwork:]) } } @@ -1122,7 +1140,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, m, m, m, work[ir:], ldworkr, work[itaup:], work[iwork:], lwork-iwork) iwork = ie + m @@ -1209,11 +1227,11 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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, + impl.Dorgbr(lapack.GeneratePT, 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) + impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) iwork = ie + m // Perform bidiagonal QR iteration, computing left singular @@ -1259,7 +1277,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float 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) + impl.Dorgbr(lapack.GenerateQ, m, m, m, u, ldu, work[itauq:], work[iwork:], lwork-iwork) iwork = ie + m // Perform bidiagonal QR iteration, computing left singular @@ -1284,7 +1302,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float // 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) + impl.Dorgbr(lapack.GenerateQ, m, m, n, u, ldu, work[itauq:], work[iwork:], lwork-iwork) } if wantvas { // If right singular vectors desired in VT, copy result to VT @@ -1296,7 +1314,7 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float } else { nrvt = m } - impl.Dorgbr(lapack.ApplyP, nrvt, n, m, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) + impl.Dorgbr(lapack.GeneratePT, nrvt, n, m, vt, ldvt, work[itaup:], work[iwork:], lwork-iwork) } if wantuo { panic(noSVDO) @@ -1339,16 +1357,16 @@ func (impl Implementation) Dgesvd(jobU, jobVT lapack.SVDJob, m, n int, a []float // Undo scaling if necessary. if iscl { if anrm > bignum { - impl.Dlascl(lapack.General, 0, 0, bignum, anrm, minmn, 1, s, minmn) + impl.Dlascl(lapack.General, 0, 0, bignum, anrm, 1, minmn, s, minmn) } if !ok && anrm > bignum { - impl.Dlascl(lapack.General, 0, 0, bignum, anrm, minmn-1, 1, work[minmn:], minmn) + impl.Dlascl(lapack.General, 0, 0, bignum, anrm, 1, minmn-1, work[1:], minmn) } if anrm < smlnum { - impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, minmn, 1, s, minmn) + impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, 1, minmn, s, minmn) } if !ok && anrm < smlnum { - impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, minmn-1, 1, work[minmn:], minmn) + impl.Dlascl(lapack.General, 0, 0, smlnum, anrm, 1, minmn-1, work[1:], minmn) } } work[0] = float64(maxwrk) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go index 1256bf34323..63ad72e99e0 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetf2.go @@ -29,14 +29,29 @@ import ( // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - if m == 0 || n == 0 { + + // Quick return if possible. + if mn == 0 { return true } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(ipiv) != mn: + panic(badLenIpiv) + } + bi := blas64.Implementation() + sfmin := dlamchS ok = true for j := 0; j < mn; j++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go index 7c0cc25bb29..ad01e71e4eb 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrf.go @@ -28,23 +28,38 @@ import ( // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - if m == 0 || n == 0 { - return false + + // Quick return if possible. + if mn == 0 { + return true } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(ipiv) != mn: + panic(badLenIpiv) + } + bi := blas64.Implementation() + nb := impl.Ilaenv(1, "DGETRF", " ", m, n, -1, -1) - if nb <= 1 || nb >= min(m, n) { + if nb <= 1 || mn <= nb { // 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:]) + blockOk := impl.Dgetf2(m-j, jb, a[j*lda+j:], lda, ipiv[j:j+jb]) if !blockOk { ok = false } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go index 47f6306e8d5..b2f2ae46b92 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetri.go @@ -22,71 +22,95 @@ import ( // 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) + iws := max(1, n) + switch { + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < iws && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } + + if n == 0 { + work[0] = 1 + return true + } + 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 + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(ipiv) != n: + panic(badLenIpiv) } + + // Form inv(U). 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 1 < nb && nb < n { + iws = max(n*nb, 1) if lwork < iws { - nb = lwork / ldwork + nb = lwork / n nbmin = max(2, impl.Ilaenv(2, "DGETRI", " ", n, -1, -1, -1)) } } + ldwork := nb + bi := blas64.Implementation() + // Solve the equation inv(A)*L = inv(U) for inv(A). // TODO(btracey): Replace this with a more row-major oriented algorithm. - if nb < nbmin || nb >= n { + if nb < nbmin || n <= nb { // Unblocked code. for j := n - 1; j >= 0; j-- { for i := j + 1; i < n; i++ { - work[i*ldwork] = a[i*lda+j] + // Copy current column of L to work and replace with zeros. + work[i] = 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) + // Compute current column of inv(A). + if j < n-1 { + bi.Dgemv(blas.NoTrans, n, n-j-1, -1, a[(j+1):], lda, work[(j+1):], 1, 1, a[j:], lda) } } } else { + // Blocked code. 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++ { + // Copy current block column of L to work and replace + // with zeros. + for jj := j; jj < j+jb; jj++ { for i := jj + 1; i < n; i++ { work[i*ldwork+(jj-j)] = a[i*lda+jj] a[i*lda+jj] = 0 } } + // Compute current block column of inv(A). 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) } + bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, jb, 1, work[j*ldwork:], ldwork, a[j:], lda) } } + // Apply column interchanges. for j := n - 2; j >= 0; j-- { jp := ipiv[j] if jp != j { bi.Dswap(n, a[j:], lda, a[jp:], lda) } } + work[0] = float64(iws) return true } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go index da7e0c63696..ecc20d7c968 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dgetrs.go @@ -21,18 +21,35 @@ import ( // 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) + switch { + case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: + panic(badTrans) + case n < 0: + panic(nLT0) + case nrhs < 0: + panic(nrhsLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, nrhs): + panic(badLdB) } + + // Quick return if possible. if n == 0 || nrhs == 0 { return } - if trans != blas.Trans && trans != blas.NoTrans { - panic(badTrans) + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(b) < (n-1)*ldb+nrhs: + panic(shortB) + case len(ipiv) != n: + panic(badLenIpiv) } + bi := blas64.Implementation() + if trans == blas.NoTrans { // Solve A * X = B. impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, 1) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go index be6e8da7e37..ac234dce33b 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvd3.go @@ -108,43 +108,38 @@ import ( // 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 { + switch { + case !wantu && jobU != lapack.GSVDNone: + panic(badGSVDJob + "U") + case !wantv && jobV != lapack.GSVDNone: + panic(badGSVDJob + "V") + case !wantq && 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) { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case p < 0: + panic(pLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + case ldu < 1, wantu && ldu < m: + panic(badLdU) + case ldv < 1, wantv && ldv < p: + panic(badLdV) + case ldq < 1, wantq && ldq < n: + panic(badLdQ) + case len(iwork) < n: + panic(shortWork) + case lwork < 1 && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): panic(shortWork) - } - if len(iwork) < n { - panic(badWork) } // Determine optimal work length. @@ -166,9 +161,26 @@ func (impl Implementation) Dggsvd3(jobU, jobV, jobQ lapack.GSVDJob, m, n, p int, return 0, 0, true } + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(b) < (p-1)*ldb+n: + panic(shortB) + case wantu && len(u) < (m-1)*ldu+m: + panic(shortU) + case wantv && len(v) < (p-1)*ldv+p: + panic(shortV) + case wantq && len(q) < (n-1)*ldq+n: + panic(shortQ) + case len(alpha) != n: + panic(badLenAlpha) + case len(beta) != n: + panic(badLenBeta) + } + // 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) + anorm := impl.Dlange(lapack.Frobenius, m, n, a, lda, nil) + bnorm := impl.Dlange(lapack.Frobenius, p, n, b, ldb, nil) // Get machine precision and set up threshold for determining // the effective numerical rank of the matrices A and B. diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go index 19187968e75..7a9ad9fbf96 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dggsvp3.go @@ -54,43 +54,38 @@ import ( // // 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 { + switch { + case !wantu && jobU != lapack.GSVDNone: + panic(badGSVDJob + "U") + case !wantv && jobV != lapack.GSVDNone: + panic(badGSVDJob + "V") + case !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) + case m < 0: + panic(mLT0) + case p < 0: + panic(pLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + case ldu < 1, wantu && ldu < m: + panic(badLdU) + case ldv < 1, wantv && ldv < p: + panic(badLdV) + case ldq < 1, wantq && ldq < n: + panic(badLdQ) + case len(iwork) != n: + panic(shortWork) + case lwork < 1 && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } var lwkopt int @@ -112,13 +107,26 @@ func (impl Implementation) Dggsvp3(jobU, jobV, jobQ lapack.GSVDJob, m, p, n int, 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) + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(b) < (p-1)*ldb+n: + panic(shortB) + case wantu && len(u) < (m-1)*ldu+m: + panic(shortU) + case wantv && len(v) < (p-1)*ldv+p: + panic(shortV) + case wantq && len(q) < (n-1)*ldq+n: + panic(shortQ) + case len(tau) < n: + // tau check must come after lwkopt query since + // the Dggsvd3 call for lwkopt query may have + // lwork == -1, and tau is provided by work. + panic(shortTau) } + const forward = true + // QR with column pivoting of B: B*P = V*[ S11 S12 ]. // [ 0 0 ] for i := range iwork[:n] { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go index c9deee90633..ed3fbca8514 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dhseqr.go @@ -27,11 +27,11 @@ import ( // 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 +// If compz == lapack.SchurNone, 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 +// If compz == lapack.SchurHess, 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 +// If compz == lapack.SchurOrig, 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. // @@ -96,11 +96,11 @@ import ( // 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 +// If unconverged > 0 and compz == lapack.SchurOrig, 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 +// If unconverged > 0 and compz == lapack.SchurHess, then on return // (final Z) = U, // where U is the orthogonal matrix in (*) regardless of the value of job. // @@ -118,45 +118,53 @@ import ( // 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 - } +func (impl Implementation) Dhseqr(job lapack.SchurJob, compz lapack.SchurComp, n, ilo, ihi int, h []float64, ldh int, wr, wi []float64, z []float64, ldz int, work []float64, lwork int) (unconverged int) { + wantt := job == lapack.EigenvaluesAndSchur + wantz := compz == lapack.SchurHess || compz == lapack.SchurOrig + switch { + case job != lapack.EigenvaluesOnly && job != lapack.EigenvaluesAndSchur: + panic(badSchurJob) + case compz != lapack.SchurNone && compz != lapack.SchurHess && compz != lapack.SchurOrig: + panic(badSchurComp) 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 ldh < max(1, n): + panic(badLdH) + case ldz < 1, wantz && ldz < n: + panic(badLdZ) case lwork < max(1, n) && lwork != -1: - panic(badWork) + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } - 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") - } + + // 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, h, ldh, wr, wi, ilo, ihi, z, ldz, work, -1, 1) + work[0] = math.Max(float64(n), work[0]) + return 0 + } + + switch { + case len(h) < (n-1)*ldh+n: + panic(shortH) + case wantz && len(z) < (n-1)*ldz+n: + panic(shortZ) + case len(wr) < n: + panic(shortWr) + case len(wi) < n: + panic(shortWi) } const ( @@ -173,19 +181,6 @@ func (impl Implementation) Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, 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] @@ -197,7 +192,7 @@ func (impl Implementation) Dhseqr(job lapack.EVJob, compz lapack.EVComp, n, ilo, } // Initialize Z to identity matrix if requested. - if compz == lapack.HessEV { + if compz == lapack.SchurHess { impl.Dlaset(blas.All, n, n, 0, 1, z, ldz) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go index 0527ebef1c1..babc0b7c0d7 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlabrd.go @@ -53,25 +53,48 @@ import ( // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case nb < 0: + panic(nbLT0) + case nb > n: + panic(nbGTN) + case nb > m: + panic(nbGTM) + case lda < max(1, n): + panic(badLdA) + case ldx < max(1, nb): + panic(badLdX) + case ldy < max(1, nb): + panic(badLdY) } - if len(e) < nb { - panic(badE) - } - if len(tauQ) < nb { - panic(badTauQ) - } - if len(tauP) < nb { - panic(badTauP) - } - if m <= 0 || n <= 0 { + + if m == 0 || n == 0 || nb == 0 { return } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(d) < nb: + panic(shortD) + case len(e) < nb: + panic(shortE) + case len(tauQ) < nb: + panic(shortTauQ) + case len(tauP) < nb: + panic(shortTauP) + case len(x) < (m-1)*ldx+nb: + panic(shortX) + case len(y) < (n-1)*ldy+nb: + panic(shortY) + } + bi := blas64.Implementation() + if m >= n { // Reduce to upper bidiagonal form. for i := 0; i < nb; i++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go index 751d5caa9bb..e8ac1e439c4 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacn2.go @@ -28,22 +28,24 @@ import ( // // 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") + switch { + case n < 1: + panic(nLT1) + case len(v) < n: + panic(shortV) + case len(x) < n: + panic(shortX) + case len(isgn) < n: + panic(shortIsgn) + case isave[0] < 0 || 5 < isave[0]: + panic(badIsave) + case isave[0] == 0 && kase != 0: + panic(badIsave) } - 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 + + const itmax = 5 bi := blas64.Implementation() + if kase == 0 { for i := 0; i < n; i++ { x[i] = 1 / float64(n) @@ -53,8 +55,6 @@ func (impl Implementation) Dlacn2(n int, v, x []float64, isgn []int, est float64 return est, kase } switch isave[0] { - default: - panic("unreachable") case 1: if n == 1 { v[0] = x[0] diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go index 2fe952d5888..a37f3b0dbdf 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlacpy.go @@ -12,18 +12,37 @@ import "gonum.org/v1/gonum/blas" // // 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: + switch { + case uplo != blas.Upper && uplo != blas.Lower && uplo != blas.All: panic(badUplo) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, n): + panic(badLdB) + } + + if m == 0 || n == 0 { + return + } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(b) < (m-1)*ldb+n: + panic(shortB) + } + + switch uplo { 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++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go index 8ffe2ebaa84..2b79bd8ae7f 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaexc.go @@ -35,26 +35,34 @@ import ( // // 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") + switch { + case n < 0: + panic(nLT0) + case ldt < max(1, n): + panic(badLdT) + case wantq && ldt < max(1, n): + panic(badLdQ) + case j1 < 0 || n <= j1: + panic(badJ1) + case len(work) < n: + panic(shortWork) + case n1 < 0 || 2 < n1: + panic(badN1) + case n2 < 0 || 2 < n2: + panic(badN2) } if n == 0 || n1 == 0 || n2 == 0 { return true } + + switch { + case len(t) < (n-1)*ldt+n: + panic(shortT) + case wantq && len(q) < (n-1)*ldq+n: + panic(shortQ) + } + 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 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go index 66330ab8b92..00a869bce8b 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahqr.go @@ -72,33 +72,41 @@ import ( // // 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: + case n < 0: + panic(nLT0) + case ilo < 0, max(0, ihi) < ilo: panic(badIlo) - case n <= ihi: + case ihi >= n: 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") - } + case ldh < max(1, n): + panic(badLdH) + case wantz && (iloz < 0 || ilo < iloz): + panic(badIloz) + case wantz && (ihiz < ihi || n <= ihiz): + panic(badIhiz) + case ldz < 1, wantz && ldz < n: + panic(badLdZ) } // Quick return if possible. if n == 0 { return 0 } + + switch { + case len(h) < (n-1)*ldh+n: + panic(shortH) + case len(wr) != ihi+1: + panic(shortWr) + case len(wi) != ihi+1: + panic(shortWi) + case wantz && len(z) < (n-1)*ldz+n: + panic(shortZ) + case ilo > 0 && h[ilo*ldh+ilo-1] != 0: + panic(notIsolated) + } + if ilo == ihi { wr[ilo] = h[ilo*ldh+ilo] wi[ilo] = 0 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go index 9d23bc060cb..a47dc8fed12 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlahr2.go @@ -65,15 +65,41 @@ import ( // // 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) + switch { + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case nb < 0: + panic(nbLT0) + case nb > n: + panic(nbGTN) + case lda < max(1, n-k+1): + panic(badLdA) + case ldt < max(1, nb): + panic(badLdT) + case ldy < max(1, nb): + panic(badLdY) } - checkMatrix(nb, nb, t, ldt) - checkMatrix(n, nb, y, ldy) // Quick return if possible. - if n <= 1 { + if n < 0 { + return + } + + switch { + case len(a) < (n-1)*lda+n-k+1: + panic(shortA) + case len(tau) < nb: + panic(shortTau) + case len(t) < (nb-1)*ldt+nb: + panic(shortT) + case len(y) < (n-1)*ldy+nb: + panic(shortY) + } + + // Quick return if possible. + if n == 1 { return } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go index 07cf5213cfd..ca0b2f78c8d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaln2.go @@ -57,15 +57,24 @@ func (impl Implementation) Dlaln2(trans bool, na, nw int, smin, ca float64, a [] // would be simpler and more natural, and the implementation not as // convoluted. - if na != 1 && na != 2 { - panic("lapack: invalid value of na") + switch { + case na != 1 && na != 2: + panic(badNa) + case nw != 1 && nw != 2: + panic(badNw) + case lda < na: + panic(badLdA) + case len(a) < (na-1)*lda+na: + panic(shortA) + case ldb < nw: + panic(badLdB) + case len(b) < (na-1)*ldb+nw: + panic(shortB) + case ldx < nw: + panic(badLdX) + case len(x) < (na-1)*ldx+nw: + panic(shortX) } - 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 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go index 76bce5ec3c7..9edfa83c43a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlange.go @@ -15,23 +15,30 @@ import ( // 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. +// 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 (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: + switch { + case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: panic(badNorm) + case lda < max(1, n): + panic(badLdA) } - if norm == lapack.MaxColumnSum && len(work) < n { - panic(badWork) - } - if m == 0 && n == 0 { + + // Quick return if possible. + if m == 0 || n == 0 { return 0 } + + switch { + case len(a) < (m-1)*lda+n: + panic(badLdA) + case norm == lapack.MaxColumnSum && len(work) < n: + panic(shortWork) + } + if norm == lapack.MaxAbs { var value float64 for i := 0; i < m; i++ { @@ -43,7 +50,7 @@ func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, } if norm == lapack.MaxColumnSum { if len(work) < n { - panic(badWork) + panic(shortWork) } for i := 0; i < n; i++ { work[i] = 0 @@ -70,15 +77,13 @@ func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, } 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 + // norm == lapack.Frobenius + 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) } - panic("lapack: bad matrix norm") + value = scale * math.Sqrt(sum) + return value } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go index 74eafeb2866..9ca1897e34b 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlanst.go @@ -14,15 +14,22 @@ import ( // 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) + switch { + case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: + panic(badNorm) + case n < 0: + panic(nLT0) } - if len(e) < n-1 { - panic(badE) - } - if n <= 0 { + if n == 0 { return 0 } + switch { + case len(d) < n: + panic(shortD) + case len(e) < n-1: + panic(shortE) + } + switch norm { default: panic(badNorm) @@ -55,7 +62,7 @@ func (impl Implementation) Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) } } return anorm - case lapack.NormFrob: + case lapack.Frobenius: var scale float64 sum := 1.0 if n > 1 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go index 2a380d21026..97ba5b24381 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlansy.go @@ -15,25 +15,32 @@ import ( // 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: + switch { + case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: panic(badNorm) - } - if (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n { - panic(badWork) - } - if uplo != blas.Upper && uplo != blas.Lower { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } + // Quick return if possible. if n == 0 { return 0 } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case (norm == lapack.MaxColumnSum || norm == lapack.MaxRowSum) && len(work) < n: + panic(shortWork) + } + switch norm { default: - panic("unreachable") + panic(badNorm) case lapack.MaxAbs: if uplo == blas.Upper { var max float64 @@ -98,7 +105,7 @@ func (impl Implementation) Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, } } return max - case lapack.NormFrob: + case lapack.Frobenius: if uplo == blas.Upper { var sum float64 for i := 0; i < n; i++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go index 25702cff3b0..cc96391d943 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlantr.go @@ -15,27 +15,35 @@ import ( // 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: + switch { + case norm != lapack.MaxRowSum && norm != lapack.MaxColumnSum && norm != lapack.Frobenius && norm != lapack.MaxAbs: panic(badNorm) - } - if uplo != blas.Upper && uplo != blas.Lower { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) - } - if diag != blas.Unit && diag != blas.NonUnit { + case diag != blas.Unit && diag != blas.NonUnit: panic(badDiag) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - if norm == lapack.MaxColumnSum && len(work) < n { - panic(badWork) - } - if min(m, n) == 0 { + + // Quick return if possible. + minmn := min(m, n) + if minmn == 0 { return 0 } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case norm == lapack.MaxColumnSum && len(work) < n: + panic(shortWork) + } + switch norm { default: - panic("unreachable") + panic(badNorm) case lapack.MaxAbs: if diag == blas.Unit { value := 1.0 @@ -95,10 +103,10 @@ func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag b return value case lapack.MaxColumnSum: if diag == blas.Unit { - for i := 0; i < min(m, n); i++ { + for i := 0; i < minmn; i++ { work[i] = 1 } - for i := min(m, n); i < n; i++ { + for i := minmn; i < n; i++ { work[i] = 0 } if uplo == blas.Upper { @@ -148,7 +156,7 @@ func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag b if uplo == blas.Upper { for i := 0; i < m; i++ { var sum float64 - if i < min(m, n) { + if i < minmn { sum = 1 } for j := i + 1; j < n; j++ { @@ -165,7 +173,7 @@ func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag b } else { for i := 1; i < m; i++ { var sum float64 - if i < min(m, n) { + if i < minmn { sum = 1 } for j := 0; j < min(i, n); j++ { @@ -211,7 +219,7 @@ func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag b return maxsum } } - case lapack.NormFrob: + case lapack.Frobenius: var nrm float64 if diag == blas.Unit { if uplo == blas.Upper { @@ -229,7 +237,7 @@ func (impl Implementation) Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag b } } } - nrm += float64(min(m, n)) + nrm += float64(minmn) } else { if uplo == blas.Upper { for i := 0; i < m; i++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go index cb5c0b7ef38..bf98c338ebf 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapll.go @@ -14,10 +14,29 @@ import "gonum.org/v1/gonum/blas/blas64" // // 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) + switch { + case n < 0: + panic(nLT0) + case incX <= 0: + panic(badIncX) + case incY <= 0: + panic(badIncY) + } - if n <= 1 { + // Quick return if possible. + if n == 0 { + return 0 + } + + switch { + case len(x) < 1+(n-1)*incX: + panic(shortX) + case len(y) < 1+(n-1)*incY: + panic(shortY) + } + + // Quick return if possible. + if n == 1 { return 0 } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go index f5a5b1fd6e0..55f1567f3ab 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlapmt.go @@ -19,12 +19,29 @@ import "gonum.org/v1/gonum/blas/blas64" // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case ldx < max(1, n): + panic(badLdX) } - if n <= 1 { + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + switch { + case len(x) < (m-1)*ldx+n: + panic(shortX) + case len(k) != n: + panic(badLenK) + } + + // Quick return if possible. + if n == 1 { return } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go index 80f43905e6b..d3a0def6391 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqp2.go @@ -34,22 +34,38 @@ import ( // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case offset < 0: + panic(offsetLT0) + case offset > m: + panic(offsetGTM) + case lda < max(1, n): + panic(badLdA) } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + 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) + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(jpvt) != n: + panic(badLenJpvt) + case len(tau) < mn: + panic(shortTau) + case len(vn1) < n: + panic(shortVn1) + case len(vn2) < n: + panic(shortVn2) + case len(work) < n: + panic(shortWork) } tol3z := math.Sqrt(dlamchE) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go index 89cfd094cad..dd683b62aea 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqps.go @@ -49,28 +49,55 @@ import ( // // 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 { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case offset < 0: + panic(offsetLT0) + case offset > m: panic(offsetGTM) + case nb < 0: + panic(nbLT0) + case nb > n: + panic(nbGTN) + case lda < max(1, n): + panic(badLdA) + case ldf < max(1, nb): + panic(badLdF) } - if n < 0 || nb > n { - panic(badNb) + + if m == 0 || n == 0 { + return 0 } - if len(jpvt) != n { - panic(badIpiv) + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(jpvt) != n: + panic(badLenJpvt) + case len(vn1) < n: + panic(shortVn1) + case len(vn2) < n: + panic(shortVn2) } - if len(tau) < nb { - panic(badTau) + + if nb == 0 { + return 0 } - if len(vn1) < n { - panic(badVn1) + + switch { + case len(tau) < nb: + panic(shortTau) + case len(auxv) < nb: + panic(shortAuxv) + case len(f) < (n-1)*ldf+nb: + panic(shortF) } - if len(vn2) < n { - panic(badVn2) - } - if len(auxv) < nb { - panic(badAuxv) + + if offset == m { + return 0 } lastrk := min(m, n+offset) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go index 945c657de53..e9fbb6007e6 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr04.go @@ -123,46 +123,32 @@ func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float ) 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 lwork < 1 && n <= ntiny && lwork != -1: - panic(badWork) + case ldh < max(1, n): + panic(badLdH) + case wantz && (iloz < 0 || ilo < iloz): + panic(badIloz) + case wantz && (ihiz < ihi || n <= ihiz): + panic(badIhiz) + case ldz < 1, wantz && ldz < n: + panic(badLdZ) + case lwork < 1 && lwork != -1: + panic(badLWork) // 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(badLWork) + case len(work) < max(1, 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") - } + panic(recurLT0) } // Quick return. @@ -171,10 +157,27 @@ func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float return 0 } + if lwork != -1 { + switch { + case len(h) < (n-1)*ldh+n: + panic(shortH) + case len(wr) != ihi+1: + panic(badLenWr) + case len(wi) != ihi+1: + panic(badLenWi) + case wantz && len(z) < (n-1)*ldz+n: + panic(shortZ) + case ilo > 0 && h[ilo*ldh+ilo-1] != 0: + panic(notIsolated) + case ihi+1 < n && h[(ihi+1)*ldh+ihi] != 0: + panic(notIsolated) + } + } + if n <= ntiny { // Tiny matrices must use Dlahqr. - work[0] = 1 if lwork == -1 { + work[0] = 1 return 0 } return impl.Dlahqr(wantt, wantz, n, ilo, ihi, h, ldh, wr, wi, iloz, ihiz, z, ldz) @@ -217,8 +220,8 @@ func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float 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) + impl.Dlaqr23(wantt, wantz, n, ilo, ihi, nwr+1, h, ldh, iloz, ihiz, z, ldz, + wr, wi, h, ldh, n, h, ldh, n, h, ldh, work, -1, recur) // Optimal workspace is max(Dlaqr5, Dlaqr23). lwkopt := max(3*nsr/2, int(work[0])) // Quick return in case of workspace query. @@ -381,7 +384,7 @@ func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float 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) + wr[ks:ks+ns], wi[ks:ks+ns], 0, 0, nil, 1) } // In case of a rare QR failure use eigenvalues // of the trailing 2×2 principal submatrix. @@ -440,7 +443,7 @@ func (impl Implementation) Dlaqr04(wantt, wantz bool, n, ilo, ihi int, h []float } } - // Use up to ns of the the smallest magnitude shifts. If there + // Use up to ns of 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 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go index 493b8e445e7..e21373bd101 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr1.go @@ -18,15 +18,17 @@ import "math" // // 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)) { + switch { + case n != 2 && n != 3: + panic("lapack: n must be 2 or 3") + case ldh < n: + panic(badLdH) + case len(h) < (n-1)*ldh+n: + panic(shortH) + case !((sr1 == sr2 && si1 == -si2) || (si1 == 0 && si2 == 0)): panic(badShifts) + case len(v) != n: + panic(shortV) } if n == 2 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go index 24fdf12b8d6..ff299a73aaf 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr23.go @@ -80,48 +80,38 @@ import ( // 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 n < 0: + panic(nLT0) case ktop < 0 || max(0, n-1) < ktop: - panic("lapack: invalid value of ktop") + panic(badKtop) 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") + panic(badKbot) + case nw < 0 || kbot-ktop+1+1 < nw: + panic(badNw) + case ldh < max(1, n): + panic(badLdH) + case wantz && (iloz < 0 || ktop < iloz): + panic(badIloz) + case wantz && (ihiz < kbot || n <= ihiz): + panic(badIhiz) + case ldz < 1, wantz && ldz < n: + panic(badLdZ) + case ldv < max(1, nw): + panic(badLdV) case nh < nw: - panic("lapack: invalid value of nh") + panic(badNh) + case ldt < max(1, nh): + panic(badLdT) + case nv < 0: + panic(nvLT0) + case ldwv < max(1, nw): + panic(badLdWV) case lwork < max(1, 2*nw) && lwork != -1: - panic(badWork) - case len(work) < lwork: + panic(badLWork) + case len(work) < max(1, 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") - } + panic(recurLT0) } // Quick return for zero window size. @@ -137,14 +127,14 @@ func (impl Implementation) Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h [ lwkopt := max(1, 2*nw) if jw > 2 { // Workspace query call to Dgehrd. - impl.Dgehrd(jw, 0, jw-2, nil, 0, nil, work, -1) + impl.Dgehrd(jw, 0, jw-2, t, ldt, work, 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) + impl.Dormhr(blas.Right, blas.NoTrans, jw, jw, 0, jw-2, t, ldt, work, v, ldv, 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) + impl.Dlaqr04(true, true, jw, 0, jw-1, t, ldt, sr, si, 0, jw-1, v, ldv, work, -1, recur-1) lwk3 := int(work[0]) // Optimal workspace. lwkopt = max(jw+max(lwk1, lwk2), lwk3) @@ -159,6 +149,28 @@ func (impl Implementation) Dlaqr23(wantt, wantz bool, n, ktop, kbot, nw int, h [ return 0, 0 } + // Check input slices only if not doing workspace query. + switch { + case len(h) < (n-1)*ldh+n: + panic(shortH) + case len(v) < (nw-1)*ldv+nw: + panic(shortV) + case len(t) < (nw-1)*ldt+nh: + panic(shortT) + case len(wv) < (nv-1)*ldwv+nw: + panic(shortWV) + case wantz && len(z) < (n-1)*ldz+n: + panic(shortZ) + case len(sr) != kbot+1: + panic(badLenSr) + case len(si) != kbot+1: + panic(badLenSi) + case ktop > 0 && h[ktop*ldh+ktop-1] != 0: + panic(notIsolated) + case kbot+1 < n && h[(kbot+1)*ldh+kbot] != 0: + panic(notIsolated) + } + // Machine constants. ulp := dlamchP smlnum := float64(n) / ulp * dlamchS diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go index 48198122c26..c198f229a2d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaqr5.go @@ -67,40 +67,68 @@ import ( // // 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") + switch { + case kacc22 != 0 && kacc22 != 1 && kacc22 != 2: + panic(badKacc22) + case n < 0: + panic(nLT0) + case ktop < 0 || n <= ktop: + panic(badKtop) + case kbot < 0 || n <= kbot: + panic(badKbot) + + case nshfts < 0: + panic(nshftsLT0) + case nshfts&0x1 != 0: + panic(nshftsOdd) + case len(sr) != nshfts: + panic(badLenSr) + case len(si) != nshfts: + panic(badLenSi) + + case ldh < max(1, n): + panic(badLdH) + case len(h) < (n-1)*ldh+n: + panic(shortH) + + case wantz && ihiz >= n: + panic(badIhiz) + case wantz && iloz < 0 || ihiz < iloz: + panic(badIloz) + case ldz < 1, wantz && ldz < n: + panic(badLdZ) + case wantz && len(z) < (n-1)*ldz+n: + panic(shortZ) + + case ldv < 3: + // V is transposed w.r.t. reference lapack. + panic(badLdV) + case len(v) < (nshfts/2-1)*ldv+3: + panic(shortV) + + case ldu < max(1, 3*nshfts-3): + panic(badLdU) + case len(u) < (3*nshfts-3-1)*ldu+3*nshfts-3: + panic(shortU) + + case nv < 0: + panic(nvLT0) + case ldwv < max(1, 3*nshfts-3): + panic(badLdWV) + case len(wv) < (nv-1)*ldwv+3*nshfts-3: + panic(shortWV) + + case nh < 0: + panic(nhLT0) + case ldwh < max(1, nh): + panic(badLdWH) + case len(wh) < (3*nshfts-3-1)*ldwh+nh: + panic(shortWH) + + case ktop > 0 && h[ktop*ldh+ktop-1] != 0: + panic(notIsolated) + case kbot < n-1 && h[(kbot+1)*ldh+kbot] != 0: + panic(notIsolated) } // If there are no shifts, then there is nothing to do. @@ -320,7 +348,7 @@ func (impl Implementation) Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot, h[j*ldh+k+3] -= refsum * v[m*ldv+2] } if accum { - // Accumulate U. (If necessary, update Z later with with an + // Accumulate U. (If necessary, update Z later with an // efficient matrix-matrix multiply.) kms := k - incol for j := max(0, ktop-incol-1); j < kdu; j++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go index 5fe24f4a9cf..9fc97a3285e 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarf.go @@ -22,19 +22,37 @@ import ( // // 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) + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case incv == 0: + panic(zeroIncV) + case ldc < max(1, n): + panic(badLdC) } - checkMatrix(m, n, c, ldc) - // v has length m if applyleft and n otherwise. + if m == 0 || n == 0 { + return + } + + applyleft := side == blas.Left lenV := n if applyleft { lenV = m } - checkVector(lenV, v, incv) + switch { + case len(v) < 1+(lenV-1)*abs(incv): + panic(shortV) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case (applyleft && len(work) < n) || (!applyleft && len(work) < m): + panic(shortWork) + } lastv := 0 // last non-zero element of v lastc := 0 // last non-zero row/column of c diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go index 3de2684b15b..4dd8e063acc 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfb.go @@ -56,40 +56,58 @@ import ( // // 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) + switch { + case side != blas.Left && side != blas.Right: + panic(badSide) + case trans != blas.Trans && trans != blas.NoTrans: + panic(badTrans) + case direct != lapack.Forward && direct != lapack.Backward: + panic(badDirect) + case store != lapack.ColumnWise && store != lapack.RowWise: + panic(badStoreV) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case store == lapack.ColumnWise && ldv < max(1, k): + panic(badLdV) + case store == lapack.RowWise && ldv < max(1, nv): + panic(badLdV) + case ldt < max(1, k): + panic(badLdT) + case ldc < max(1, n): + panic(badLdC) + case ldwork < max(1, k): + panic(badLdWork) } - checkMatrix(nw, k, work, ldwork) if m == 0 || n == 0 { return } + nw := n + if side == blas.Right { + nw = m + } + switch { + case store == lapack.ColumnWise && len(v) < (nv-1)*ldv+k: + panic(shortV) + case store == lapack.RowWise && len(v) < (k-1)*ldv+nv: + panic(shortV) + case len(t) < (k-1)*ldt+k: + panic(shortT) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case len(work) < (nw-1)*ldwork+k: + panic(shortWork) + } + bi := blas64.Implementation() transt := blas.Trans diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go index 52a67a46b71..e037fdd6bdd 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfg.go @@ -23,14 +23,23 @@ import ( // // 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 { + switch { + case n < 0: panic(nLT0) + case incX <= 0: + panic(badIncX) } + if n <= 1 { return alpha, 0 } - checkVector(n-1, x, incX) + + if len(x) < 1+(n-2)*abs(incX) { + panic(shortX) + } + bi := blas64.Implementation() + xnorm := bi.Dnrm2(n-1, x, incX) if xnorm == 0 { return alpha, 0 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go index eaec8132042..8f03eb8b3b7 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarft.go @@ -28,25 +28,41 @@ import ( // 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) { +func (Implementation) Dlarft(direct lapack.Direct, store lapack.StoreV, n, k int, v []float64, ldv int, tau []float64, t []float64, ldt int) { + mv, nv := n, k + if store == lapack.RowWise { + mv, nv = k, n + } + switch { + case direct != lapack.Forward && direct != lapack.Backward: + panic(badDirect) + case store != lapack.RowWise && store != lapack.ColumnWise: + panic(badStoreV) + case n < 0: + panic(nLT0) + case k < 1: + panic(kLT1) + case ldv < max(1, nv): + panic(badLdV) + case len(tau) < k: + panic(shortTau) + case ldt < max(1, k): + panic(shortT) + } + if n == 0 { return } - if n < 0 || k < 0 { - panic(negDimension) + + switch { + case len(v) < (mv-1)*ldv+nv: + panic(shortV) + case len(t) < (k-1)*ldt+k: + panic(shortT) } - 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. diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go index 6b3f905c0b8..d7928c8cf47 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlarfx.go @@ -27,20 +27,35 @@ import "gonum.org/v1/gonum/blas" // // 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: + switch { + case side != blas.Left && side != blas.Right: panic(badSide) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case ldc < max(1, n): + panic(badLdC) + } + + // Quick return if possible. + if m == 0 || n == 0 { + return + } + + nh := m + lwork := n + if side == blas.Right { + nh = n + lwork = m + } + switch { + case len(v) < nh: + panic(shortV) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case nh > 10 && len(work) < lwork: + panic(shortWork) } if tau == 0 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go index 51363fe50af..61c4eb79cb3 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlascl.go @@ -17,16 +17,40 @@ import ( // // 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) + switch kind { + default: + panic(badMatrixType) + case 'H', 'B', 'Q', 'Z': // See dlascl.f. + panic("not implemented") + case lapack.General, lapack.UpperTri, lapack.LowerTri: + if lda < max(1, n) { + panic(badLdA) + } } - if math.IsNaN(cfrom) || math.IsNaN(cto) { - panic(nanScale) + switch { + case cfrom == 0: + panic(zeroCFrom) + case math.IsNaN(cfrom): + panic(nanCFrom) + case math.IsNaN(cto): + panic(nanCTo) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) } + if n == 0 || m == 0 { return } + + switch kind { + case lapack.General, lapack.UpperTri, lapack.LowerTri: + if len(a) < (m-1)*lda+n { + panic(shortA) + } + } + smlnum := dlamchS bignum := 1 / smlnum cfromc := cfrom @@ -61,8 +85,6 @@ func (impl Implementation) Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto } } switch kind { - default: - panic("lapack: not implemented") case lapack.General: for i := 0; i < m; i++ { for j := 0; j < n; j++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go index 3116631eb28..b4e63916fb3 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaset.go @@ -14,7 +14,24 @@ import "gonum.org/v1/gonum/blas" // // 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) + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + } + + minmn := min(m, n) + if minmn == 0 { + return + } + + if len(a) < (m-1)*lda+n { + panic(shortA) + } + if uplo == blas.Upper { for i := 0; i < m; i++ { for j := i + 1; j < n; j++ { @@ -34,7 +51,7 @@ func (impl Implementation) Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, } } } - for i := 0; i < min(m, n); i++ { + for i := 0; i < minmn; i++ { a[i*lda+i] = beta } } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go index 4a37cfc550f..1f1d1dc42e3 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq1.go @@ -19,30 +19,33 @@ import ( // // 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 } + + switch { + case len(d) < n: + panic(shortD) + case len(e) < n-1: + panic(shortE) + case len(work) < 4*n: + panic(shortWork) + } + 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++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go index 009e506b61a..fd24a5509a4 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq2.go @@ -35,31 +35,34 @@ import ( // // 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 len(z) < 4*n { + panic(shortZ) + } + if n == 1 { if z[0] < 0 { panic(negZ) } return info } + + const cbias = 1.5 + + eps := dlamchP + safmin := dlamchS + tol := eps * 100 + tol2 := tol * tol if n == 2 { if z[1] < 0 || z[2] < 0 { - panic("lapack: bad z value") + panic(negZ) } else if z[2] > z[0] { z[0], z[2] = z[2], z[0] } @@ -87,7 +90,7 @@ func (impl Implementation) Dlasq2(n int, z []float64) (info int) { 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") + panic(negZ) } d += z[k] e += z[k+1] @@ -95,10 +98,9 @@ func (impl Implementation) Dlasq2(n int, z []float64) (info int) { emin = math.Min(emin, z[k+1]) } if z[2*(n-1)] < 0 { - panic("lapack: bad z value") + panic(negZ) } d += z[2*(n-1)] - qmax = math.Max(qmax, z[2*(n-1)]) // Check for diagonality. if e == 0 { for k := 1; k < n; k++ { @@ -330,7 +332,6 @@ outer: // This might need to be done for several blocks. info = 2 i1 = i0 - n1 = n0 for { tempq = z[4*i0] z[4*i0] += sigma diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go index 7139ebb5f9c..a05e94ef173 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq3.go @@ -13,6 +13,17 @@ import "math" // 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) { + switch { + case i0 < 0: + panic(i0LT0) + case n0 < 0: + panic(n0LT0) + case len(z) < 4*n0: + panic(shortZ) + case pp != 0 && pp != 1 && pp != 2: + panic(badPp) + } + const cbias = 1.5 n0in := n0 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go index 1d581a2066b..f6dbb31b98a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq4.go @@ -12,6 +12,17 @@ import "math" // // 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) { + switch { + case i0 < 0: + panic(i0LT0) + case n0 < 0: + panic(n0LT0) + case len(z) < 4*n0: + panic(shortZ) + case pp != 0 && pp != 1: + panic(badPp) + } + const ( cnst1 = 0.563 cnst2 = 1.01 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go index e9e9fbeb1cf..d3826d9186e 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq5.go @@ -13,9 +13,22 @@ import "math" 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. + + switch { + case i0 < 0: + panic(i0LT0) + case n0 < 0: + panic(n0LT0) + case len(z) < 4*n0: + panic(shortZ) + case pp != 0 && pp != 1: + panic(badPp) + } + 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 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go index f12cbf6a357..54bf5875629 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasq6.go @@ -13,12 +13,21 @@ import "math" // // 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) + switch { + case i0 < 0: + panic(i0LT0) + case n0 < 0: + panic(n0LT0) + case len(z) < 4*n0: + panic(shortZ) + case pp != 0 && pp != 1: + panic(badPp) } + 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] diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go index cc9e3910437..a7dbe002d5a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasr.go @@ -14,7 +14,7 @@ import ( // 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 +// 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]] @@ -55,34 +55,45 @@ import ( // // 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 { + switch { + case side != blas.Left && side != blas.Right: panic(badSide) - } - if pivot != lapack.Variable && pivot != lapack.Top && pivot != lapack.Bottom { + case pivot != lapack.Variable && pivot != lapack.Top && pivot != lapack.Bottom: panic(badPivot) - } - if direct != lapack.Forward && direct != lapack.Backward { + case direct != lapack.Forward && direct != lapack.Backward: panic(badDirect) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - 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) - } - } + + // Quick return if possible. if m == 0 || n == 0 { return } + + if side == blas.Left { + if len(c) < m-1 { + panic(shortC) + } + if len(s) < m-1 { + panic(shortS) + } + } else { + if len(c) < n-1 { + panic(shortC) + } + if len(s) < n-1 { + panic(shortS) + } + } + if len(a) < (m-1)*lda+n { + panic(shortA) + } + if side == blas.Left { if pivot == lapack.Variable { if direct == lapack.Forward { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go index 86786cfef60..be472805bf6 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlasrt.go @@ -17,7 +17,13 @@ import ( // // 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 { + case n < 0: + panic(nLT0) + case len(d) < n: + panic(shortD) + } + d = d[:n] switch s { default: diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go index 5a7f870909e..9c2dc7729f7 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlassq.go @@ -13,9 +13,19 @@ import "math" // // 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 { + switch { + case n < 0: + panic(nLT0) + case incx <= 0: + panic(badIncX) + case len(x) < 1+(n-1)*incx: + panic(shortX) + } + + 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) { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go index c5586e053c4..b207d1218c4 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlaswp.go @@ -25,8 +25,12 @@ func (impl Implementation) Dlaswp(n int, a []float64, lda int, k1, k2 int, ipiv panic(badK2) case k1 < 0 || k2 < k1: panic(badK1) + case lda < max(1, n): + panic(badLdA) + case len(a) < (k2-1)*lda+n: + panic(shortA) case len(ipiv) != k2+1: - panic(badIpiv) + panic(badLenIpiv) case incX != 1 && incX != -1: panic(absIncNotOne) } @@ -34,6 +38,7 @@ func (impl Implementation) Dlaswp(n int, a []float64, lda int, k1, k2 int, ipiv if n == 0 { return } + bi := blas64.Implementation() if incX == 1 { for k := k1; k <= k2; k++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go index 04eba4a0eb7..018efc98ccd 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrd.go @@ -66,18 +66,38 @@ import ( // // 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) + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case nb < 0: + panic(nbLT0) + case nb > n: + panic(nbGTN) + case lda < max(1, n): + panic(badLdA) + case ldw < max(1, nb): + panic(badLdW) } - if len(tau) < n-1 { - panic(badTau) - } - if n <= 0 { + + if n == 0 { return } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(w) < (n-1)*ldw+nb: + panic(shortW) + case len(e) < n-1: + panic(shortE) + case len(tau) < n-1: + panic(shortTau) + } + bi := blas64.Implementation() + if uplo == blas.Upper { for i := n - 1; i >= n-nb; i-- { iw := i - n + nb diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go index f0c94764e6a..dc445c6fe18 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlatrs.go @@ -18,7 +18,7 @@ import ( // 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. +// 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 @@ -28,33 +28,42 @@ import ( // // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) - } - if trans != blas.Trans && trans != blas.NoTrans { + case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: panic(badTrans) - } - if diag != blas.Unit && diag != blas.NonUnit { + case diag != blas.Unit && diag != blas.NonUnit: panic(badDiag) - } - upper := uplo == blas.Upper - noTrans := trans == blas.NoTrans - nonUnit := diag == blas.NonUnit - - if n < 0 { + case n < 0: panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - checkMatrix(n, n, a, lda) - checkVector(n, x, 1) - checkVector(n, cnorm, 1) + // Quick return if possible. if n == 0 { return 0 } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(x) < n: + panic(shortX) + case len(cnorm) < n: + panic(shortCNorm) + } + + upper := uplo == blas.Upper + nonUnit := diag == blas.NonUnit + smlnum := dlamchS / dlamchP bignum := 1 / smlnum scale = 1 + bi := blas64.Implementation() + if !normin { if upper { cnorm[0] = 0 @@ -85,7 +94,7 @@ func (impl Implementation) Dlatrs(uplo blas.Uplo, trans blas.Transpose, diag bla xbnd := xmax var grow float64 var jfirst, jlast, jinc int - if noTrans { + if trans == blas.NoTrans { if upper { jfirst = n - 1 jlast = -1 @@ -183,7 +192,7 @@ Solve: bi.Dscal(n, scale, x, 1) xmax = bignum } - if noTrans { + if trans == blas.NoTrans { for j := jfirst; j != jlast; j += jinc { xj := math.Abs(x[j]) var tjj, tjjs float64 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go new file mode 100644 index 00000000000..ecce22cc641 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlauu2.go @@ -0,0 +1,64 @@ +// Copyright ©2018 The Gonum Authors. 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 ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlauu2 computes the product +// U * U^T if uplo is blas.Upper +// L^T * L if uplo is blas.Lower +// where U or L is stored in the upper or lower triangular part of A. +// Only the upper or lower triangle of the result is stored, overwriting +// the corresponding factor in A. +func (impl Implementation) Dlauu2(uplo blas.Uplo, n int, a []float64, lda int) { + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + } + + // Quick return if possible. + if n == 0 { + return + } + + if len(a) < (n-1)*lda+n { + panic(shortA) + } + + bi := blas64.Implementation() + + if uplo == blas.Upper { + // Compute the product U*U^T. + for i := 0; i < n; i++ { + aii := a[i*lda+i] + if i < n-1 { + a[i*lda+i] = bi.Ddot(n-i, a[i*lda+i:], 1, a[i*lda+i:], 1) + bi.Dgemv(blas.NoTrans, i, n-i-1, 1, a[i+1:], lda, a[i*lda+i+1:], 1, + aii, a[i:], lda) + } else { + bi.Dscal(i+1, aii, a[i:], lda) + } + } + } else { + // Compute the product L^T*L. + for i := 0; i < n; i++ { + aii := a[i*lda+i] + if i < n-1 { + a[i*lda+i] = bi.Ddot(n-i, a[i*lda+i:], lda, a[i*lda+i:], lda) + bi.Dgemv(blas.Trans, n-i-1, i, 1, a[(i+1)*lda:], lda, a[(i+1)*lda+i:], lda, + aii, a[i*lda:], 1) + } else { + bi.Dscal(i+1, aii, a[i*lda:], 1) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go new file mode 100644 index 00000000000..67ecaddf4c5 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dlauum.go @@ -0,0 +1,81 @@ +// Copyright ©2018 The Gonum Authors. 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 ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dlauum computes the product +// U * U^T if uplo is blas.Upper +// L^T * L if uplo is blas.Lower +// where U or L is stored in the upper or lower triangular part of A. +// Only the upper or lower triangle of the result is stored, overwriting +// the corresponding factor in A. +func (impl Implementation) Dlauum(uplo blas.Uplo, n int, a []float64, lda int) { + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + } + + // Quick return if possible. + if n == 0 { + return + } + + if len(a) < (n-1)*lda+n { + panic(shortA) + } + + // Determine the block size. + opts := "U" + if uplo == blas.Lower { + opts = "L" + } + nb := impl.Ilaenv(1, "DLAUUM", opts, n, -1, -1, -1) + + if nb <= 1 || n <= nb { + // Use unblocked code. + impl.Dlauu2(uplo, n, a, lda) + return + } + + // Use blocked code. + bi := blas64.Implementation() + if uplo == blas.Upper { + // Compute the product U*U^T. + for i := 0; i < n; i += nb { + ib := min(nb, n-i) + bi.Dtrmm(blas.Right, blas.Upper, blas.Trans, blas.NonUnit, + i, ib, 1, a[i*lda+i:], lda, a[i:], lda) + impl.Dlauu2(blas.Upper, ib, a[i*lda+i:], lda) + if n-i-ib > 0 { + bi.Dgemm(blas.NoTrans, blas.Trans, i, ib, n-i-ib, + 1, a[i+ib:], lda, a[i*lda+i+ib:], lda, 1, a[i:], lda) + bi.Dsyrk(blas.Upper, blas.NoTrans, ib, n-i-ib, + 1, a[i*lda+i+ib:], lda, 1, a[i*lda+i:], lda) + } + } + } else { + // Compute the product L^T*L. + for i := 0; i < n; i += nb { + ib := min(nb, n-i) + bi.Dtrmm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, + ib, i, 1, a[i*lda+i:], lda, a[i*lda:], lda) + impl.Dlauu2(blas.Lower, ib, a[i*lda+i:], lda) + if n-i-ib > 0 { + bi.Dgemm(blas.Trans, blas.NoTrans, ib, i, n-i-ib, + 1, a[(i+ib)*lda+i:], lda, a[(i+ib)*lda:], lda, 1, a[i*lda:], lda) + bi.Dsyrk(blas.Lower, blas.Trans, ib, n-i-ib, + 1, a[(i+ib)*lda+i:], lda, 1, a[i*lda+i:], lda) + } + } + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go index 07156bf14f9..57942892723 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/doc.go @@ -16,7 +16,7 @@ // 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/golang.org/v1/gonum/blas/blas64). In particular, +// blas64 package (https://godoc.org/golang.org/v1/gonum/blas/blas64). In particular, // this implies that an external BLAS library will be used if it is // registered in blas64. // diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go index 3207198625e..a20765a9e96 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2l.go @@ -22,23 +22,34 @@ import ( // // 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 { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case n > m: + panic(nGTM) + case k < 0: + panic(kLT0) + case k > n: panic(kGTN) + case lda < max(1, n): + panic(badLdA) } + if n == 0 { return } + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(work) < n: + panic(shortWork) + } + // Initialize columns 0:n-k to columns of the unit matrix. for j := 0; j < n-k; j++ { for l := 0; l < m; l++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go index d75250171f4..de44775712d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorg2r.go @@ -17,26 +17,36 @@ import ( // // 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 { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case n > m: + panic(nGTM) + case k < 0: + panic(kLT0) + case k > n: panic(kGTN) + case lda < max(1, n): + panic(badLdA) } - if n > m { - panic(mLTN) - } - if len(work) < n { - panic(badWork) - } + if n == 0 { return } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(work) < n: + panic(shortWork) + } + 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++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go index c3c4c90ab8c..626cad5ffe6 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgbr.go @@ -10,41 +10,55 @@ import "gonum.org/v1/gonum/lapack" // 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 +// If vect == lapack.GenerateQ, 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 +// If vect == lapack.GeneratePT, 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) { +func (impl Implementation) Dorgbr(vect lapack.GenOrtho, m, n, k int, a []float64, lda int, tau, work []float64, lwork int) { + wantq := vect == lapack.GenerateQ 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) - } + switch { + case vect != lapack.GenerateQ && vect != lapack.GeneratePT: + panic(badGenOrtho) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case wantq && n > m: + panic(nGTM) + case wantq && n < min(m, k): + panic("lapack: n < min(m,k)") + case !wantq && m > n: + panic(mGTN) + case !wantq && m < min(n, k): + panic("lapack: m < min(n,k)") + case lda < max(1, n) && lwork != -1: + // Normally, we follow the reference and require the leading + // dimension to be always valid, even in case of workspace + // queries. However, if a caller provided a placeholder value + // for lda (and a) when doing a workspace query that didn't + // fulfill the condition here, it would cause a panic. This is + // exactly what Dgesvd does. + panic(badLdA) + case lwork < max(1, mn) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } + + // Quick return if possible. work[0] = 1 + if m == 0 || n == 0 { + return + } + if wantq { if m >= k { impl.Dorgqr(m, n, k, a, lda, tau, work, -1) @@ -64,16 +78,16 @@ func (impl Implementation) Dorgbr(vect lapack.DecompUpdate, m, n, k int, a []flo 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 + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case wantq && len(tau) < min(m, k): + panic(shortTau) + case !wantq && len(tau) < min(n, k): + panic(shortTau) } + if wantq { // Form Q, determined by a call to Dgebrd to reduce an m×k matrix. if m >= k { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go index b7ea7b2cf7e..6e799d10d5a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorghr.go @@ -33,29 +33,37 @@ package gonum // // 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 lda < max(1, n): + panic(badLdA) case lwork < max(1, nh) && lwork != -1: - panic(badWork) + panic(badLWork) case len(work) < max(1, lwork): panic(shortWork) } + // Quick return if possible. + if n == 0 { + work[0] = 1 + return + } + 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 + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(tau) < n-1: + panic(shortTau) } // Shift the vectors which define the elementary reflectors one column diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go index 06303812f83..b5566b9de1a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgl2.go @@ -17,26 +17,34 @@ import ( // // 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 { + switch { + case m < 0: + panic(mLT0) + case n < m: panic(nLTM) + case k < 0: + panic(kLT0) + case k > m: + panic(kGTM) + case lda < max(1, m): + panic(badLdA) } - if len(work) < m { - panic(badWork) - } + if m == 0 { return } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(work) < m: + panic(shortWork) + } + bi := blas64.Implementation() + if k < m { for i := k; i < m; i++ { for j := 0; j < n; j++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go index 4f45a6a39d7..a6dd980cebb 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorglq.go @@ -15,7 +15,7 @@ import ( // 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. +// len(tau) >= k, 0 <= k <= m, 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. @@ -26,39 +26,46 @@ import ( // // 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 { + switch { + case m < 0: + panic(mLT0) + case n < m: panic(nLTM) - } - if len(tau) < k { - panic(badTau) - } - if len(work) < lwork { + case k < 0: + panic(kLT0) + case k > m: + panic(kGTM) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, m) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): panic(shortWork) } - if lwork < m { - panic(badWork) - } + if m == 0 { + work[0] = 1 return } - nbmin := 2 // Minimum number of blocks - var nx int // Minimum number of rows + + nb := impl.Ilaenv(1, "DORGLQ", " ", m, n, k, -1) + if lwork == -1 { + work[0] = float64(m * nb) + return + } + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + } + + nbmin := 2 // Minimum block size + var nx int // Crossover size from blocked to unbloked code iws := m // Length of work needed var ldwork int - if nb > 1 && nb < k { + if 1 < nb && nb < k { nx = max(0, impl.Ilaenv(3, "DORGLQ", " ", m, n, k, -1)) if nx < k { ldwork = nb @@ -70,12 +77,11 @@ func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work [ } } } + var ki, kk int - if nb >= nbmin && nb < k && nx < k { + if nbmin <= nb && 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 + ki = ((k - nx - 1) / nb) * nb kk = min(k, ki+nb) for i := kk; i < m; i++ { for j := 0; j < kk; j++ { @@ -87,31 +93,31 @@ func (impl Implementation) Dorglq(m, n, k int, a []float64, lda int, tau, work [ // 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) + if kk > 0 { + // 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 + 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 + } } } } + work[0] = float64(iws) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go index 35967d72ed8..6927ba4ca3c 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgql.go @@ -33,26 +33,25 @@ import ( // 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 m < 0: + panic(mLT0) case n < 0: panic(nLT0) - case m < n: - panic(mLTN) + case n > m: + panic(nGTM) case k < 0: panic(kLT0) case k > n: panic(kGTN) + case lda < max(1, n): + panic(badLdA) case lwork < max(1, n) && lwork != -1: - panic(badWork) - case len(work) < lwork: + panic(badLWork) + case len(work) < max(1, lwork): panic(shortWork) } - if lwork != -1 { - checkMatrix(m, n, a, lda) - if len(tau) < k { - panic(badTau) - } - } + // Quick return if possible. if n == 0 { work[0] = 1 return @@ -64,10 +63,17 @@ func (impl Implementation) Dorgql(m, n, k int, a []float64, lda int, tau, work [ return } + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + } + nbmin := 2 var nx, ldwork int iws := n - if nb > 1 && nb < k { + if 1 < nb && 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 { @@ -84,7 +90,7 @@ func (impl Implementation) Dorgql(m, n, k int, a []float64, lda int, tau, work [ } var kk int - if nb >= nbmin && nb < k && nx < k { + if nbmin <= nb && 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) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go index 6b8fb7423e4..f07fdaf46a7 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgqr.go @@ -28,39 +28,55 @@ import ( // // 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) { + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case n > m: + panic(nGTM) + case k < 0: + panic(kLT0) + case k > n: + panic(kGTN) + case lda < max(1, n) && lwork != -1: + // Normally, we follow the reference and require the leading + // dimension to be always valid, even in case of workspace + // queries. However, if a caller provided a placeholder value + // for lda (and a) when doing a workspace query that didn't + // fulfill the condition here, it would cause a panic. This is + // exactly what Dgesvd does. + panic(badLdA) + case lwork < max(1, n) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + if n == 0 { + work[0] = 1 + return + } + 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) + work[0] = float64(n * nb) return } - checkMatrix(m, n, a, lda) - if k < 0 { - panic(kLT0) + + switch { + case len(a) < (m-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) } - 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 + + nbmin := 2 // Minimum block size + var nx int // Crossover size from blocked to unbloked code iws := n // Length of work needed var ldwork int - if nb > 1 && nb < k { + if 1 < nb && nb < k { nx = max(0, impl.Ilaenv(3, "DORGQR", " ", m, n, k, -1)) if nx < k { ldwork = nb @@ -73,14 +89,12 @@ func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work [ } } var ki, kk int - if nb >= nbmin && nb < k && nx < k { + if nbmin <= nb && 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 + ki = ((k - nx - 1) / nb) * nb kk = min(k, ki+nb) - for j := kk; j < n; j++ { - for i := 0; i < kk; i++ { + for i := 0; i < kk; i++ { + for j := kk; j < n; j++ { a[i*lda+j] = 0 } } @@ -89,32 +103,32 @@ func (impl Implementation) Dorgqr(m, n, k int, a []float64, lda int, tau, work [ // 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) + if kk > 0 { + // 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 + 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 + } } } } + work[0] = float64(iws) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go index 6984ff55e50..483fbcae9d2 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorgtr.go @@ -25,19 +25,17 @@ import "gonum.org/v1/gonum/blas" // // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, n-1) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } if n == 0 { @@ -46,7 +44,7 @@ func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, t } var nb int - if upper { + if uplo == blas.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) @@ -57,7 +55,14 @@ func (impl Implementation) Dorgtr(uplo blas.Uplo, n int, a []float64, lda int, t return } - if upper { + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(tau) < n-1: + panic(shortTau) + } + + if uplo == blas.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 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go index e8fb1d4de75..4b0bd83cc3c 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorm2r.go @@ -23,37 +23,50 @@ import "gonum.org/v1/gonum/blas" // // 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 { + left := side == blas.Left + switch { + case !left && side != blas.Right: panic(badSide) - } - if trans != blas.Trans && trans != blas.NoTrans { + case trans != blas.Trans && trans != blas.NoTrans: panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case left && k > m: + panic(kGTM) + case !left && k > n: + panic(kGTN) + case lda < max(1, k): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) } - 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) + // Quick return if possible. if m == 0 || n == 0 || k == 0 { return } - if len(tau) < k { - panic(badTau) + + switch { + case left && len(a) < (m-1)*lda+k: + panic(shortA) + case !left && len(a) < (n-1)*lda+k: + panic(shortA) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case len(tau) < k: + panic(shortTau) + case left && len(work) < n: + panic(shortWork) + case !left && len(work) < m: + panic(shortWork) } + if left { - if notran { + if trans == blas.NoTrans { for i := k - 1; i >= 0; i-- { aii := a[i*lda+i] a[i*lda+i] = 1 @@ -70,7 +83,7 @@ func (impl Implementation) Dorm2r(side blas.Side, trans blas.Transpose, m, n, k } return } - if notran { + if trans == blas.NoTrans { for i := 0; i < k; i++ { aii := a[i*lda+i] a[i*lda+i] = 1 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go index 250d23bead9..026dc04127d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormbr.go @@ -44,41 +44,44 @@ import ( // 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) - } +func (impl Implementation) Dormbr(vect lapack.ApplyOrtho, side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64, lwork int) { 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 { + applyQ := vect == lapack.ApplyQ + switch { + case !applyQ && vect != lapack.ApplyP: + panic(badApplyOrtho) + case side != blas.Left && side != blas.Right: + panic(badSide) + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case applyQ && lda < max(1, min(nq, k)): + panic(badLdA) + case !applyQ && lda < max(1, nq): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) + case lwork < max(1, nw) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): panic(shortWork) } - if lwork < max(1, nw) && lwork != -1 { - panic(badWork) - } - applyQ := vect == lapack.ApplyQ - left := side == blas.Left - var nb int + // Quick return if possible. + if m == 0 || n == 0 { + work[0] = 1 + return + } // The current implementation does not use opts, but a future change may // use these options so construct them. @@ -93,14 +96,15 @@ func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, tran } else { opts += "N" } + var nb int if applyQ { - if left { + if side == blas.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 { + if side == blas.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) @@ -109,19 +113,33 @@ func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, tran lworkopt := max(1, nw) * nb if lwork == -1 { work[0] = float64(lworkopt) + return } + + minnqk := min(nq, k) + switch { + case applyQ && len(a) < (nq-1)*lda+minnqk: + panic(shortA) + case !applyQ && len(a) < (minnqk-1)*lda+nq: + panic(shortA) + case len(tau) < minnqk: + panic(shortTau) + case len(c) < (m-1)*ldc+n: + panic(shortC) + } + 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) + impl.Dormqr(side, trans, m, n, k, a, lda, tau[:k], c, ldc, work, lwork) } else if nq > 1 { mi := m ni := n - 1 i1 := 0 i2 := 1 - if left { + if side == blas.Left { mi = m - 1 ni = n i1 = 1 @@ -132,10 +150,12 @@ func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, tran 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. @@ -146,7 +166,7 @@ func (impl Implementation) Dormbr(vect lapack.DecompUpdate, side blas.Side, tran ni := n - 1 i1 := 0 i2 := 1 - if left { + if side == blas.Left { mi = m - 1 ni = n i1 = 1 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go index f6cb1b2658d..c00f440590e 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormhr.go @@ -50,39 +50,37 @@ import "gonum.org/v1/gonum/blas" // // 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 := n // The order of Q. + nw := m // The minimum length of work. + if side == blas.Left { nq = m nw = n - case blas.Right: - nq = n - nw = m - default: - panic(badSide) } switch { + case side != blas.Left && side != blas.Right: + panic(badSide) case trans != blas.NoTrans && trans != blas.Trans: panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) case ilo < 0 || max(1, nq) <= ilo: panic(badIlo) case ihi < min(ilo, nq-1) || nq <= ihi: panic(badIhi) + case lda < max(1, nq): + panic(badLdA) case lwork < max(1, nw) && lwork != -1: - panic(badWork) + panic(badLWork) 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) - } + // Quick return if possible. + if m == 0 || n == 0 { + work[0] = 1 + return } nh := ihi - ilo @@ -106,10 +104,20 @@ func (impl Implementation) Dormhr(side blas.Side, trans blas.Transpose, m, n, il return } - if m == 0 || n == 0 || nh == 0 { + if nh == 0 { work[0] = 1 return } + + switch { + case len(a) < (nq-1)*lda+nq: + panic(shortA) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case len(tau) != nq-1: + panic(badLenTau) + } + 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) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go index 1c217b5b454..25aa83ac10d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dorml2.go @@ -23,32 +23,51 @@ import "gonum.org/v1/gonum/blas" // // 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 { + left := side == blas.Left + switch { + case !left && side != blas.Right: panic(badSide) - } - if trans != blas.Trans && trans != blas.NoTrans { + case trans != blas.Trans && trans != blas.NoTrans: panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case left && k > m: + panic(kGTM) + case !left && k > n: + panic(kGTN) + case left && lda < max(1, m): + panic(badLdA) + case !left && lda < max(1, n): + panic(badLdA) } - 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) + // Quick return if possible. if m == 0 || n == 0 || k == 0 { return } + switch { - case left && notran: + case left && len(a) < (k-1)*lda+m: + panic(shortA) + case !left && len(a) < (k-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case left && len(work) < n: + panic(shortWork) + case !left && len(work) < m: + panic(shortWork) + } + + notrans := trans == blas.NoTrans + switch { + case left && notrans: for i := 0; i < k; i++ { aii := a[i*lda+i] a[i*lda+i] = 1 @@ -56,7 +75,7 @@ func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k a[i*lda+i] = aii } - case left && !notran: + case left && !notrans: for i := k - 1; i >= 0; i-- { aii := a[i*lda+i] a[i*lda+i] = 1 @@ -64,7 +83,7 @@ func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k a[i*lda+i] = aii } - case !left && notran: + case !left && notrans: for i := k - 1; i >= 0; i-- { aii := a[i*lda+i] a[i*lda+i] = 1 @@ -72,7 +91,7 @@ func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k a[i*lda+i] = aii } - case !left && !notran: + case !left && !notrans: for i := 0; i < k; i++ { aii := a[i*lda+i] a[i*lda+i] = 1 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go index d7a27643c0a..6fcfc2fb199 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormlq.go @@ -28,33 +28,37 @@ import ( // 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) + switch { + case !left && side != blas.Right: + panic(badSide) + case trans != blas.Trans && trans != blas.NoTrans: + panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case left && k > m: + panic(kGTM) + case !left && k > n: + panic(kGTN) + case left && lda < max(1, m): + panic(badLdA) + case !left && lda < max(1, n): + panic(badLdA) + case lwork < max(1, nw) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } + // Quick return if possible. if m == 0 || n == 0 || k == 0 { work[0] = 1 return @@ -73,6 +77,17 @@ func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k return } + switch { + case left && len(a) < (k-1)*lda+m: + panic(shortA) + case !left && len(a) < (k-1)*lda+n: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(c) < (m-1)*ldc+n: + panic(shortC) + } + nbmin := 2 if 1 < nb && nb < k { iws := nw*nb + tsize @@ -92,14 +107,14 @@ func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k wrk := work[tsize:] ldwrk := nb - notran := trans == blas.NoTrans + notrans := trans == blas.NoTrans transt := blas.NoTrans - if notran { + if notrans { transt = blas.Trans } switch { - case left && notran: + case left && notrans: for i := 0; i < k; i += nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, @@ -113,7 +128,7 @@ func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k wrk, ldwrk) } - case left && !notran: + case left && !notrans: for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.RowWise, m-i, ib, @@ -127,7 +142,7 @@ func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k wrk, ldwrk) } - case !left && notran: + case !left && notrans: for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, @@ -141,7 +156,7 @@ func (impl Implementation) Dormlq(side blas.Side, trans blas.Transpose, m, n, k wrk, ldwrk) } - case !left && !notran: + case !left && !notrans: for i := 0; i < k; i += nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go index 3fa9009f89d..8ae45086548 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormqr.go @@ -37,37 +37,39 @@ import ( // 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: + left := side == blas.Left + nq := n + nw := m + if left { nq = m nw = n - case blas.Right: - nq = n - nw = m } switch { + case !left && side != blas.Right: + panic(badSide) 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 m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case left && k > m: + panic(kGTM) + case !left && k > n: + panic(kGTN) + case lda < max(1, k): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) 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) - } + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } + // Quick return if possible. if m == 0 || n == 0 || k == 0 { work[0] = 1 return @@ -86,6 +88,15 @@ func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k return } + switch { + case len(a) < (nq-1)*lda+k: + panic(shortA) + case len(tau) != k: + panic(badLenTau) + case len(c) < (m-1)*ldc+n: + panic(shortC) + } + nbmin := 2 if 1 < nb && nb < k { if lwork < nw*nb+tsize { @@ -102,12 +113,11 @@ func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k } var ( - ldwork = nb - left = side == blas.Left - notran = trans == blas.NoTrans + ldwork = nb + notrans = trans == blas.NoTrans ) switch { - case left && notran: + case left && notrans: for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, @@ -121,7 +131,7 @@ func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k work[tsize:], ldwork) } - case left && !notran: + case left && !notrans: for i := 0; i < k; i += nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.ColumnWise, m-i, ib, @@ -135,7 +145,7 @@ func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k work[tsize:], ldwork) } - case !left && notran: + case !left && notrans: for i := 0; i < k; i += nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, @@ -149,7 +159,7 @@ func (impl Implementation) Dormqr(side blas.Side, trans blas.Transpose, m, n, k work[tsize:], ldwork) } - case !left && !notran: + case !left && !notrans: for i := ((k - 1) / nb) * nb; i >= 0; i -= nb { ib := min(nb, k-i) impl.Dlarft(lapack.Forward, lapack.ColumnWise, n-i, ib, diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go index 3a6b43304e6..bb03f32c769 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dormr2.go @@ -23,42 +23,52 @@ import "gonum.org/v1/gonum/blas" // // 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 + nq := n + nw := m 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) - } + nq = m + nw = n } - if len(tau) < k { - panic(badTau) + switch { + case !left && side != blas.Right: + panic(badSide) + case trans != blas.NoTrans && trans != blas.Trans: + panic(badTrans) + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case k < 0: + panic(kLT0) + case left && k > m: + panic(kGTM) + case !left && k > n: + panic(kGTN) + case lda < max(1, nq): + panic(badLdA) + case ldc < max(1, n): + panic(badLdC) } - checkMatrix(m, n, c, ldc) + // Quick return if possible. if m == 0 || n == 0 || k == 0 { return } + + switch { + case len(a) < (k-1)*lda+nq: + panic(shortA) + case len(tau) < k: + panic(shortTau) + case len(c) < (m-1)*ldc+n: + panic(shortC) + case len(work) < nw: + panic(shortWork) + } + if left { - if notran { + if trans == blas.NoTrans { for i := k - 1; i >= 0; i-- { aii := a[i*lda+(m-k+i)] a[i*lda+(m-k+i)] = 1 @@ -75,7 +85,7 @@ func (impl Implementation) Dormr2(side blas.Side, trans blas.Transpose, m, n, k } return } - if notran { + if trans == blas.NoTrans { for i := 0; i < k; i++ { aii := a[i*lda+(n-k+i)] a[i*lda+(n-k+i)] = 1 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go index 0c60385bb9a..a5beb80bca2 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpbtf2.go @@ -48,14 +48,27 @@ import ( // // Dpbtf2 is an internal routine, exported for testing purposes. func (Implementation) Dpbtf2(ul blas.Uplo, n, kd int, ab []float64, ldab int) (ok bool) { - if ul != blas.Upper && ul != blas.Lower { + switch { + case ul != blas.Upper && ul != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case kd < 0: + panic(kdLT0) + case ldab < kd+1: + panic(badLdA) } - checkSymBanded(ab, n, kd, ldab) + if n == 0 { return } + + if len(ab) < (n-1)*ldab+kd { + panic(shortAB) + } + bi := blas64.Implementation() + kld := max(1, ldab-1) if ul == blas.Upper { for j := 0; j < n; j++ { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go index 98d6c02b075..7af4c18728e 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpocon.go @@ -21,41 +21,55 @@ import ( // // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case anorm < 0: + panic(negANorm) } - if len(work) < 3*n { - panic(badWork) - } - if len(iwork) < n { - panic(badWork) - } - var rcond float64 + + // Quick return if possible. if n == 0 { return 1 } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(work) < 3*n: + panic(shortWork) + case len(iwork) < n: + panic(shortIWork) + } + if anorm == 0 { - return rcond + return 0 } 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 + + var ( + smlnum = dlamchS + rcond float64 + sl, su float64 + normin bool + ainvnm float64 + kase int + isave [3]int + ) for { - ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) + 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 { + if uplo == blas.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:]) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go index 3d1cfb68dbc..5d3327c2d51 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotf2.go @@ -19,16 +19,26 @@ import ( // // 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 { + switch { + case ul != blas.Upper && ul != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - checkMatrix(n, n, a, lda) + // Quick return if possible. if n == 0 { return true } + if len(a) < (n-1)*lda+n { + panic(shortA) + } + bi := blas64.Implementation() + if ul == blas.Upper { for j := 0; j < n; j++ { ajj := a[j*lda+j] diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go index 0ff3afcc4fb..21241687f84 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrf.go @@ -15,15 +15,24 @@ import ( // 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 { + switch { + case ul != blas.Upper && ul != blas.Lower: panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - checkMatrix(n, n, a, lda) + // Quick return if possible. if n == 0 { return true } + if len(a) < (n-1)*lda+n { + panic(shortA) + } + nb := impl.Ilaenv(1, "DPOTRF", string(ul), n, -1, -1, -1) if nb <= 1 || n <= nb { return impl.Dpotf2(ul, n, a, lda) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go new file mode 100644 index 00000000000..2394775c311 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotri.go @@ -0,0 +1,44 @@ +// Copyright ©2019 The Gonum Authors. 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 "gonum.org/v1/gonum/blas" + +// Dpotri computes the inverse of a real symmetric positive definite matrix A +// using its Cholesky factorization. +// +// On entry, a contains the triangular factor U or L from the Cholesky +// factorization A = U^T*U or A = L*L^T, as computed by Dpotrf. +// On return, a contains the upper or lower triangle of the (symmetric) +// inverse of A, overwriting the input factor U or L. +func (impl Implementation) Dpotri(uplo blas.Uplo, n int, a []float64, lda int) (ok bool) { + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + } + + // Quick return if possible. + if n == 0 { + return true + } + + if len(a) < (n-1)*lda+n { + panic(shortA) + } + + // Invert the triangular Cholesky factor U or L. + ok = impl.Dtrtri(uplo, blas.NonUnit, n, a, lda) + if !ok { + return false + } + + // Form inv(U)*inv(U)^T or inv(L)^T*inv(L). + impl.Dlauum(uplo, n, a, lda) + return true +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go new file mode 100644 index 00000000000..689e0439c2d --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dpotrs.go @@ -0,0 +1,62 @@ +// Copyright ©2018 The Gonum Authors. 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 ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +// Dpotrs solves a system of n linear equations A*X = B where A is an n×n +// symmetric positive definite matrix and B is an n×nrhs matrix. The matrix A is +// represented by its Cholesky factorization +// A = U^T*U if uplo == blas.Upper +// A = L*L^T if uplo == blas.Lower +// as computed by Dpotrf. On entry, B contains the right-hand side matrix B, on +// return it contains the solution matrix X. +func (Implementation) Dpotrs(uplo blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int) { + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case nrhs < 0: + panic(nrhsLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, nrhs): + panic(badLdB) + } + + // Quick return if possible. + if n == 0 || nrhs == 0 { + return + } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(b) < (n-1)*ldb+nrhs: + panic(shortB) + } + + bi := blas64.Implementation() + + if uplo == blas.Upper { + // Solve U^T * U * X = B where U is stored in the upper triangle of A. + + // Solve U^T * X = B, overwriting B with X. + bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) + // Solve U * X = B, overwriting B with X. + bi.Dtrsm(blas.Left, blas.Upper, blas.NoTrans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) + } else { + // Solve L * L^T * X = B where L is stored in the lower triangle of A. + + // Solve L * X = B, overwriting B with X. + bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) + // Solve L^T * X = B, overwriting B with X. + bi.Dtrsm(blas.Left, blas.Lower, blas.Trans, blas.NonUnit, n, nrhs, 1, a, lda, b, ldb) + } +} diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go b/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go index 302c3230111..b2772dbc224 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/drscl.go @@ -15,8 +15,24 @@ import ( // // 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) + switch { + case n < 0: + panic(nLT0) + case incX <= 0: + panic(badIncX) + } + + // Quick return if possible. + if n == 0 { + return + } + + if len(x) < 1+(n-1)*incX { + panic(shortX) + } + bi := blas64.Implementation() + cden := a cnum := 1.0 smlnum := dlamchS diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go index 0e1125e5e8d..d6c7861ab5b 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsteqr.go @@ -26,46 +26,49 @@ import ( // 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 +// tridiagonal form if compz == lapack.EVOrig. On exit, if +// compz == lapack.EVOrig, z contains the orthonormal eigenvectors of the +// original symmetric matrix, and if compz == lapack.EVTridiag, z contains the // orthonormal eigenvectors of the symmetric tridiagonal matrix. z is not used -// if compz == lapack.None. +// if compz == lapack.EVCompNone. // // 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 { + switch { + case compz != lapack.EVCompNone && compz != lapack.EVTridiag && compz != lapack.EVOrig: 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 + case n < 0: + panic(nLT0) + case ldz < 1, compz != lapack.EVCompNone && ldz < n: + panic(badLdZ) } + // Quick return if possible. if n == 0 { return true } + + switch { + case len(d) < n: + panic(shortD) + case len(e) < n-1: + panic(shortE) + case compz != lapack.EVCompNone && len(z) < (n-1)*ldz+n: + panic(shortZ) + case compz != lapack.EVCompNone && len(work) < max(1, 2*n-2): + panic(shortWork) + } + + var icompz int + if compz == lapack.EVOrig { + icompz = 1 + } else if compz == lapack.EVTridiag { + icompz = 2 + } + if n == 1 { if icompz == 2 { z[0] = 1 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go index 636cf1eb6ad..dc1e178dfa1 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsterf.go @@ -26,14 +26,21 @@ func (impl Implementation) Dsterf(n int, d, e []float64) (ok bool) { if n < 0 { panic(nLT0) } + + // Quick return if possible. if n == 0 { return true } - if len(d) < n { - panic(badD) + + switch { + case len(d) < n: + panic(shortD) + case len(e) < n-1: + panic(shortE) } - if len(e) < n-1 { - panic(badE) + + if n == 1 { + return true } const ( diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go index b4c20c75a7e..5f57f3a5c97 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsyev.go @@ -19,47 +19,64 @@ import ( // 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. +// portion specified by uplo. If jobz == lapack.EVCompute, a contains the +// orthonormal eigenvectors of A on exit, otherwise jobz must be lapack.EVNone +// and 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 + switch { + case jobz != lapack.EVNone && jobz != lapack.EVCompute: + panic(badEVJob) + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < max(1, 3*n-1) && lwork != -1: + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) + } + + // Quick return if possible. + if n == 0 { + return true + } + var opts string - if upper { + if uplo == blas.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 { + work[0] = float64(lworkopt) return } - if len(work) < lwork { - panic(badWork) - } - if lwork < 3*n-1 { - panic(badWork) - } - if n == 0 { - return true + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(w) < n: + panic(shortW) } + if n == 1 { w[0] = a[0] work[0] = 2 - if wantz { + if jobz == lapack.EVCompute { a[0] = 1 } return true } + safmin := dlamchS eps := dlamchP smlnum := safmin / eps @@ -80,7 +97,7 @@ func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []f } if scaled { kind := lapack.LowerTri - if upper { + if uplo == blas.Upper { kind = lapack.UpperTri } impl.Dlascl(kind, 0, 0, 1, sigma, n, n, a, lda) @@ -93,7 +110,7 @@ func (impl Implementation) Dsyev(jobz lapack.EVJob, uplo blas.Uplo, n int, a []f // For eigenvalues only, call Dsterf. For eigenvectors, first call Dorgtr // to generate the orthogonal matrix, then call Dsteqr. - if !wantz { + if jobz == lapack.EVNone { ok = impl.Dsterf(n, w, work[inde:]) } else { impl.Dorgtr(uplo, n, a, lda, work[indtau:], work[indwork:], llwork) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go index b6dc60c036e..23cfd05773f 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytd2.go @@ -9,15 +9,15 @@ import ( "gonum.org/v1/gonum/blas/blas64" ) -// Dsytd2 reduces a symmetric n×n matrix A to symmetric tridiagonal form T by an -// orthogonal similarity transformation +// 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. +// are overwritten with 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. @@ -49,20 +49,33 @@ import ( // // 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) + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - if len(e) < n-1 { - panic(badE) - } - if len(tau) < n-1 { - panic(badTau) - } - if n <= 0 { + + // Quick return if possible. + if n == 0 { return } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(d) < n: + panic(shortD) + case len(e) < n-1: + panic(shortE) + case len(tau) < n-1: + panic(shortTau) + } + bi := blas64.Implementation() + if uplo == blas.Upper { // Reduce the upper triangle of A. for i := n - 2; i >= 0; i-- { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go index b079140cf41..df47568e92f 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dsytrd.go @@ -55,68 +55,62 @@ import ( // // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + case lwork < 1 && lwork != -1: + panic(badLWork) + case len(work) < max(1, 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) - } + // Quick return if possible. if n == 0 { work[0] = 1 return } - nb := impl.Ilaenv(1, "DSYTRD", opts, n, -1, -1, -1) + nb := impl.Ilaenv(1, "DSYTRD", string(uplo), n, -1, -1, -1) lworkopt := n * nb if lwork == -1 { work[0] = float64(lworkopt) return } - nx := n + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(d) < n: + panic(shortD) + case len(e) < n-1: + panic(shortE) + case len(tau) < n-1: + panic(shortTau) + } + bi := blas64.Implementation() + + nx := n + iws := 1 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)) + nx = max(nb, impl.Ilaenv(3, "DSYTRD", string(uplo), n, -1, -1, -1)) if nx < n { // Determine if workspace is large enough for blocked code. ldwork = nb - iws := n * ldwork + 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) + nbmin := impl.Ilaenv(2, "DSYTRD", string(uplo), n, -1, -1, -1) if nb < nbmin { nx = n } @@ -129,7 +123,7 @@ func (impl Implementation) Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d } ldwork = nb - if upper { + if uplo == blas.Upper { // Reduce the upper triangle of A. Columns 0:kk are handled by the // unblocked method. var i int @@ -174,5 +168,5 @@ func (impl Implementation) Dsytrd(uplo blas.Uplo, n int, a []float64, lda int, d // 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) + work[0] = float64(iws) } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go index 8a1beefe302..d70d1962342 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtgsja.go @@ -159,45 +159,61 @@ import ( 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) + switch { + case !initu && !wantu && jobU != lapack.GSVDNone: + panic(badGSVDJob + "U") + case !initv && !wantv && jobV != lapack.GSVDNone: + panic(badGSVDJob + "V") + case !initq && !wantq && jobQ != lapack.GSVDNone: + panic(badGSVDJob + "Q") + case m < 0: + panic(mLT0) + case p < 0: + panic(pLT0) + case n < 0: + panic(nLT0) + + case lda < max(1, n): + panic(badLdA) + case len(a) < (m-1)*lda+n: + panic(shortA) + + case ldb < max(1, n): + panic(badLdB) + case len(b) < (p-1)*ldb+n: + panic(shortB) + + case len(alpha) != n: + panic(badLenAlpha) + case len(beta) != n: + panic(badLenBeta) + + case ldu < 1, wantu && ldu < m: + panic(badLdU) + case wantu && len(u) < (m-1)*ldu+m: + panic(shortU) + + case ldv < 1, wantv && ldv < p: + panic(badLdV) + case wantv && len(v) < (p-1)*ldv+p: + panic(shortV) + + case ldq < 1, wantq && ldq < n: + panic(badLdQ) + case wantq && len(q) < (n-1)*ldq+n: + panic(shortQ) + + case len(work) < 2*n: + panic(shortWork) } // Initialize U, V and Q, if necessary diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go index 42d9648f43c..899c95dd58c 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrcon.go @@ -19,24 +19,32 @@ import ( // // 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 { + switch { + case norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum: panic(badNorm) - } - if uplo != blas.Upper && uplo != blas.Lower { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) - } - if diag != blas.NonUnit && diag != blas.Unit { + case diag != blas.NonUnit && diag != blas.Unit: panic(badDiag) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - if len(work) < 3*n { - panic(badWork) - } - if len(iwork) < n { - panic(badWork) - } + if n == 0 { return 1 } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(work) < 3*n: + panic(shortWork) + case len(iwork) < n: + panic(shortIWork) + } + bi := blas64.Implementation() var rcond float64 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go index 6e9a335402f..17121b8dbf0 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go @@ -31,21 +31,21 @@ import ( // 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. +// If side == lapack.EVRight, only right eigenvectors will be computed. +// If side == lapack.EVLeft, only left eigenvectors will be computed. +// If side == lapack.EVBoth, 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 +// If howmny == lapack.EVAll, all right and/or left eigenvectors will be // computed. -// If howmny == lapack.AllEVMulQ, all right and/or left eigenvectors will be +// If howmny == lapack.EVAllMulQ, 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 +// If howmny == lapack.EVSelected, 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 howmny == lapack.EVSelected, 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, @@ -53,38 +53,38 @@ import ( // 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 +// VL and VR are n×mm matrices. If howmny is lapack.EVAll or +// lapack.AllEVMulQ, mm must be at least n. If howmny is +// lapack.EVSelected, 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 +// On entry, if howmny is lapack.EVAllMulQ, it is assumed that VL (if side +// is lapack.EVLeft or lapack.EVBoth) contains an n×n matrix QL, +// and that VR (if side is lapack.EVLeft or lapack.EVBoth) 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, +// On return, if side is lapack.EVLeft or lapack.EVBoth, // 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 +// if howmny == lapack.EVAll, the matrix Y of left eigenvectors of T, +// if howmny == lapack.EVAllMulQ, the matrix Q*Y, +// if howmny == lapack.EVSelected, 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. +// VL is not referenced if side == lapack.EVRight. // -// On return, if side is lapack.RightEV or lapack.RightLeftEV, +// On return, if side is lapack.EVRight or lapack.EVBoth, // 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 +// if howmny == lapack.EVAll, the matrix X of right eigenvectors of T, +// if howmny == lapack.EVAllMulQ, the matrix Q*X, +// if howmny == lapack.EVSelected, 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. +// VR is not referenced if side == lapack.EVLeft. // // 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 @@ -105,88 +105,112 @@ import ( // 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(badEVSide) - case lapack.RightEV, lapack.LeftEV, lapack.RightLeftEV: - } - switch howmny { - default: - panic(badHowMany) - case lapack.AllEV, lapack.AllEVMulQ, lapack.SelectedEV: - } +func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.EVHowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) (m int) { + bothv := side == lapack.EVBoth + rightv := side == lapack.EVRight || bothv + leftv := side == lapack.EVLeft || bothv switch { + case !rightv && !leftv: + panic(badEVSide) + case howmny != lapack.EVAll && howmny != lapack.EVAllMulQ && howmny != lapack.EVSelected: + panic(badEVHowMany) case n < 0: panic(nLT0) - case len(work) < lwork: - panic(shortWork) + case ldt < max(1, n): + panic(badLdT) + case mm < 0: + panic(mmLT0) + case ldvl < 1: + // ldvl and ldvr are also checked below after the computation of + // m (number of columns of VL and VR) in case of howmny == EVSelected. + panic(badLdVL) + case ldvr < 1: + panic(badLdVR) 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) - } + panic(badLWork) + case len(work) < max(1, lwork): + panic(shortWork) } // Quick return if possible. if n == 0 { work[0] = 1 - return m + return 0 } - const ( - nbmin = 8 - nbmax = 128 - ) - nb := impl.Ilaenv(1, "DTREVC", string(side)+string(howmny), n, -1, -1, -1) + // Normally we don't check slice lengths until after the workspace + // query. However, even in case of the workspace query we need to + // compute and return the value of m, and since the computation accesses t, + // we put the length check of t here. + if len(t) < (n-1)*ldt+n { + panic(shortT) + } + + if howmny == lapack.EVSelected { + if len(selected) != n { + panic(badLenSelected) + } + // Set m to the number of columns required to store the selected + // eigenvectors, and standardize the slice selected. + // Each selected real eigenvector occupies one column and each + // selected complex eigenvector occupies two columns. + 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 mm < m { + panic(badMm) + } // Quick return in case of a workspace query. + nb := impl.Ilaenv(1, "DTREVC", string(side)+string(howmny), n, -1, -1, -1) if lwork == -1 { work[0] = float64(n + 2*n*nb) return m } + // Quick return if no eigenvectors were selected. + if m == 0 { + return 0 + } + + switch { + case leftv && ldvl < mm: + panic(badLdVL) + case leftv && len(vl) < (n-1)*ldvl+mm: + panic(shortVL) + + case rightv && ldvr < mm: + panic(badLdVR) + case rightv && len(vr) < (n-1)*ldvr+mm: + panic(shortVR) + } + // 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 { + const ( + nbmin = 8 + nbmax = 128 + ) + if howmny == lapack.EVAllMulQ && 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 { @@ -230,7 +254,7 @@ func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, se iscomplex [nbmax]int // Stores ip for each column in current block. ) - if side == lapack.LeftEV { + if side == lapack.EVLeft { goto leftev } @@ -261,7 +285,7 @@ func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, se ip = -1 } - if howmny == lapack.SelectedEV { + if howmny == lapack.EVSelected { if ip == 0 { if !selected[ki] { continue @@ -336,7 +360,7 @@ func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, se } // Copy the vector x or Q*x to VR and normalize. switch { - case howmny != lapack.AllEVMulQ: + case howmny != lapack.EVAllMulQ: // 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) @@ -447,7 +471,7 @@ func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, se // Copy the vector x or Q*x to VR and normalize. switch { - case howmny != lapack.AllEVMulQ: + case howmny != lapack.EVAllMulQ: // 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) @@ -539,7 +563,7 @@ func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, se } } - if side == lapack.RightEV { + if side == lapack.EVRight { return m } @@ -569,7 +593,7 @@ leftev: // conjugate pair. ip = 1 } - if howmny == lapack.SelectedEV && !selected[ki] { + if howmny == lapack.EVSelected && !selected[ki] { continue } @@ -603,7 +627,6 @@ leftev: 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. @@ -626,7 +649,6 @@ leftev: 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) @@ -648,7 +670,7 @@ leftev: } // Copy the vector x or Q*x to VL and normalize. switch { - case howmny != lapack.AllEVMulQ: + case howmny != lapack.EVAllMulQ: // 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 @@ -711,7 +733,6 @@ leftev: 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) @@ -738,7 +759,6 @@ leftev: 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) @@ -767,7 +787,7 @@ leftev: } // Copy the vector x or Q*x to VL and normalize. switch { - case howmny != lapack.AllEVMulQ: + case howmny != lapack.EVAllMulQ: // 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) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go index 40e03785b0e..9f3f90bad8d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrexc.go @@ -18,8 +18,8 @@ import "gonum.org/v1/gonum/lapack" // 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 by post-multiplying it with Z. +// If compq is lapack.UpdateSchurNone, the matrix Q is not referenced and will not be // updated. // For other values of compq Dtrexc will panic. // @@ -45,32 +45,38 @@ import "gonum.org/v1/gonum/lapack" // 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) +func (impl Implementation) Dtrexc(compq lapack.UpdateSchurComp, n int, t []float64, ldt int, q []float64, ldq int, ifst, ilst int, work []float64) (ifstOut, ilstOut int, ok bool) { + switch { + case compq != lapack.UpdateSchur && compq != lapack.UpdateSchurNone: + panic(badUpdateSchurComp) + case n < 0: + panic(nLT0) + case ldt < max(1, n): + panic(badLdT) + case ldq < 1, compq == lapack.UpdateSchur && ldq < n: + panic(badLdQ) + case (ifst < 0 || n <= ifst) && n > 0: + panic(badIfst) + case (ilst < 0 || n <= ilst) && n > 0: + panic(badIlst) } - 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 { + if n == 0 { + return ifst, ilst, true + } + + switch { + case len(t) < (n-1)*ldt+n: + panic(shortT) + case compq == lapack.UpdateSchur && len(q) < (n-1)*ldq+n: + panic(shortQ) + case len(work) < n: + panic(shortWork) + } + + // Quick return if possible. + if n == 1 { return ifst, ilst, true } @@ -93,6 +99,9 @@ func (impl Implementation) Dtrexc(compq lapack.EVComp, n int, t []float64, ldt i nbl = 2 } + ok = true + wantq := compq == lapack.UpdateSchur + switch { case ifst == ilst: return ifst, ilst, true diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go index a43efe6fd79..efc24b65ea2 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrti2.go @@ -14,13 +14,25 @@ import ( // // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) - } - if diag != blas.NonUnit && diag != blas.Unit { + case diag != blas.NonUnit && diag != blas.Unit: panic(badDiag) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } + + if n == 0 { + return + } + + if len(a) < (n-1)*lda+n { + panic(shortA) + } + bi := blas64.Implementation() nonUnit := diag == blas.NonUnit diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go index 95f1b3be4d5..6ec3663c35d 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtri.go @@ -16,18 +16,26 @@ import ( // 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 { + switch { + case uplo != blas.Upper && uplo != blas.Lower: panic(badUplo) - } - if diag != blas.NonUnit && diag != blas.Unit { + case diag != blas.NonUnit && diag != blas.Unit: panic(badDiag) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } + if n == 0 { - return false + return true } - nonUnit := diag == blas.NonUnit - if nonUnit { + + if len(a) < (n-1)*lda+n { + panic(shortA) + } + + if diag == blas.NonUnit { for i := 0; i < n; i++ { if a[i*lda+i] == 0 { return false diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go index e1782d232f2..1752dc5c856 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrtrs.go @@ -12,11 +12,36 @@ import ( // 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 + switch { + case uplo != blas.Upper && uplo != blas.Lower: + panic(badUplo) + case trans != blas.NoTrans && trans != blas.Trans && trans != blas.ConjTrans: + panic(badTrans) + case diag != blas.NonUnit && diag != blas.Unit: + panic(badDiag) + case n < 0: + panic(nLT0) + case nrhs < 0: + panic(nrhsLT0) + case lda < max(1, n): + panic(badLdA) + case ldb < max(1, nrhs): + panic(badLdB) } + + if n == 0 { + return true + } + + switch { + case len(a) < (n-1)*lda+n: + panic(shortA) + case len(b) < (n-1)*ldb+nrhs: + panic(shortB) + } + // Check for singularity. + nounit := diag == blas.NonUnit if nounit { for i := 0; i < n; i++ { if a[i*lda+i] == 0 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/errors.go b/vendor/gonum.org/v1/gonum/lapack/gonum/errors.go new file mode 100644 index 00000000000..3c0cb68efe7 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/errors.go @@ -0,0 +1,174 @@ +// Copyright ©2015 The Gonum Authors. 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 + +// This list is duplicated in netlib/lapack/netlib. Keep in sync. +const ( + // Panic strings for bad enumeration values. + badApplyOrtho = "lapack: bad ApplyOrtho" + badBalanceJob = "lapack: bad BalanceJob" + badDiag = "lapack: bad Diag" + badDirect = "lapack: bad Direct" + badEVComp = "lapack: bad EVComp" + badEVHowMany = "lapack: bad EVHowMany" + badEVJob = "lapack: bad EVJob" + badEVSide = "lapack: bad EVSide" + badGSVDJob = "lapack: bad GSVDJob" + badGenOrtho = "lapack: bad GenOrtho" + badLeftEVJob = "lapack: bad LeftEVJob" + badMatrixType = "lapack: bad MatrixType" + badNorm = "lapack: bad Norm" + badPivot = "lapack: bad Pivot" + badRightEVJob = "lapack: bad RightEVJob" + badSVDJob = "lapack: bad SVDJob" + badSchurComp = "lapack: bad SchurComp" + badSchurJob = "lapack: bad SchurJob" + badSide = "lapack: bad Side" + badSort = "lapack: bad Sort" + badStoreV = "lapack: bad StoreV" + badTrans = "lapack: bad Trans" + badUpdateSchurComp = "lapack: bad UpdateSchurComp" + badUplo = "lapack: bad Uplo" + bothSVDOver = "lapack: both jobU and jobVT are lapack.SVDOverwrite" + + // Panic strings for bad numerical and string values. + badIfst = "lapack: ifst out of range" + badIhi = "lapack: ihi out of range" + badIhiz = "lapack: ihiz out of range" + badIlo = "lapack: ilo out of range" + badIloz = "lapack: iloz out of range" + badIlst = "lapack: ilst out of range" + badIsave = "lapack: bad isave value" + badIspec = "lapack: bad ispec value" + badJ1 = "lapack: j1 out of range" + badJpvt = "lapack: bad element of jpvt" + badK1 = "lapack: k1 out of range" + badK2 = "lapack: k2 out of range" + badKacc22 = "lapack: invalid value of kacc22" + badKbot = "lapack: kbot out of range" + badKtop = "lapack: ktop out of range" + badLWork = "lapack: insufficient declared workspace length" + badMm = "lapack: mm out of range" + badN1 = "lapack: bad value of n1" + badN2 = "lapack: bad value of n2" + badNa = "lapack: bad value of na" + badName = "lapack: bad name" + badNh = "lapack: bad value of nh" + badNw = "lapack: bad value of nw" + badPp = "lapack: bad value of pp" + badShifts = "lapack: bad shifts" + i0LT0 = "lapack: i0 < 0" + kGTM = "lapack: k > m" + kGTN = "lapack: k > n" + kLT0 = "lapack: k < 0" + kLT1 = "lapack: k < 1" + kdLT0 = "lapack: kd < 0" + mGTN = "lapack: m > n" + mLT0 = "lapack: m < 0" + mmLT0 = "lapack: mm < 0" + n0LT0 = "lapack: n0 < 0" + nGTM = "lapack: n > m" + nLT0 = "lapack: n < 0" + nLT1 = "lapack: n < 1" + nLTM = "lapack: n < m" + nanCFrom = "lapack: cfrom is NaN" + nanCTo = "lapack: cto is NaN" + nbGTM = "lapack: nb > m" + nbGTN = "lapack: nb > n" + nbLT0 = "lapack: nb < 0" + nccLT0 = "lapack: ncc < 0" + ncvtLT0 = "lapack: ncvt < 0" + negANorm = "lapack: anorm < 0" + negZ = "lapack: negative z value" + nhLT0 = "lapack: nh < 0" + notIsolated = "lapack: block is not isolated" + nrhsLT0 = "lapack: nrhs < 0" + nruLT0 = "lapack: nru < 0" + nshftsLT0 = "lapack: nshfts < 0" + nshftsOdd = "lapack: nshfts must be even" + nvLT0 = "lapack: nv < 0" + offsetGTM = "lapack: offset > m" + offsetLT0 = "lapack: offset < 0" + pLT0 = "lapack: p < 0" + recurLT0 = "lapack: recur < 0" + zeroCFrom = "lapack: zero cfrom" + + // Panic strings for bad slice lengths. + badLenAlpha = "lapack: bad length of alpha" + badLenBeta = "lapack: bad length of beta" + badLenIpiv = "lapack: bad length of ipiv" + badLenJpvt = "lapack: bad length of jpvt" + badLenK = "lapack: bad length of k" + badLenSelected = "lapack: bad length of selected" + badLenSi = "lapack: bad length of si" + badLenSr = "lapack: bad length of sr" + badLenTau = "lapack: bad length of tau" + badLenWi = "lapack: bad length of wi" + badLenWr = "lapack: bad length of wr" + + // Panic strings for insufficient slice lengths. + shortA = "lapack: insufficient length of a" + shortAB = "lapack: insufficient length of ab" + shortAuxv = "lapack: insufficient length of auxv" + shortB = "lapack: insufficient length of b" + shortC = "lapack: insufficient length of c" + shortCNorm = "lapack: insufficient length of cnorm" + shortD = "lapack: insufficient length of d" + shortE = "lapack: insufficient length of e" + shortF = "lapack: insufficient length of f" + shortH = "lapack: insufficient length of h" + shortIWork = "lapack: insufficient length of iwork" + shortIsgn = "lapack: insufficient length of isgn" + shortQ = "lapack: insufficient length of q" + shortS = "lapack: insufficient length of s" + shortScale = "lapack: insufficient length of scale" + shortT = "lapack: insufficient length of t" + shortTau = "lapack: insufficient length of tau" + shortTauP = "lapack: insufficient length of tauP" + shortTauQ = "lapack: insufficient length of tauQ" + shortU = "lapack: insufficient length of u" + shortV = "lapack: insufficient length of v" + shortVL = "lapack: insufficient length of vl" + shortVR = "lapack: insufficient length of vr" + shortVT = "lapack: insufficient length of vt" + shortVn1 = "lapack: insufficient length of vn1" + shortVn2 = "lapack: insufficient length of vn2" + shortW = "lapack: insufficient length of w" + shortWH = "lapack: insufficient length of wh" + shortWV = "lapack: insufficient length of wv" + shortWi = "lapack: insufficient length of wi" + shortWork = "lapack: insufficient length of work" + shortWr = "lapack: insufficient length of wr" + shortX = "lapack: insufficient length of x" + shortY = "lapack: insufficient length of y" + shortZ = "lapack: insufficient length of z" + + // Panic strings for bad leading dimensions of matrices. + badLdA = "lapack: bad leading dimension of A" + badLdB = "lapack: bad leading dimension of B" + badLdC = "lapack: bad leading dimension of C" + badLdF = "lapack: bad leading dimension of F" + badLdH = "lapack: bad leading dimension of H" + badLdQ = "lapack: bad leading dimension of Q" + badLdT = "lapack: bad leading dimension of T" + badLdU = "lapack: bad leading dimension of U" + badLdV = "lapack: bad leading dimension of V" + badLdVL = "lapack: bad leading dimension of VL" + badLdVR = "lapack: bad leading dimension of VR" + badLdVT = "lapack: bad leading dimension of VT" + badLdW = "lapack: bad leading dimension of W" + badLdWH = "lapack: bad leading dimension of WH" + badLdWV = "lapack: bad leading dimension of WV" + badLdWork = "lapack: bad leading dimension of Work" + badLdX = "lapack: bad leading dimension of X" + badLdY = "lapack: bad leading dimension of Y" + badLdZ = "lapack: bad leading dimension of Z" + + // Panic strings for bad vector increments. + absIncNotOne = "lapack: increment not one or negative one" + badIncX = "lapack: incX <= 0" + badIncY = "lapack: incY <= 0" + zeroIncV = "lapack: incv == 0" +) diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/general.go b/vendor/gonum.org/v1/gonum/lapack/gonum/general.go deleted file mode 100644 index a82d996973c..00000000000 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/general.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright ©2015 The Gonum Authors. 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 ( - "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" - badZ = "lapack: insufficient z length" - kGTM = "lapack: k > m" - kGTN = "lapack: k > n" - kLT0 = "lapack: k < 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 checkSymBanded(ab []float64, n, kd, lda int) { - if n < 0 { - panic("lapack: negative banded length") - } - if kd < 0 { - panic("lapack: negative bandwidth value") - } - if lda < kd+1 { - panic("lapack: stride less than number of bands") - } - if len(ab) < (n-1)*lda+kd { - panic("lapack: insufficient banded vector 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/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go index bd0e4d8fe8e..b251d72691e 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlc.go @@ -9,10 +9,22 @@ package gonum // // 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 + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) + } + + if n == 0 || m == 0 { + return -1 + } + + if len(a) < (m-1)*lda+n { + panic(shortA) } - 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 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go index 9f9e0d93772..b73fe18ea2a 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/iladlr.go @@ -9,11 +9,22 @@ package gonum // // 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 + switch { + case m < 0: + panic(mLT0) + case n < 0: + panic(nLT0) + case lda < max(1, n): + panic(badLdA) } - checkMatrix(m, n, a, lda) + if n == 0 || m == 0 { + return -1 + } + + if len(a) < (m-1)*lda+n { + panic(shortA) + } // Check the common case where the corner is non-zero if a[(m-1)*lda] != 0 || a[(m-1)*lda+n-1] != 0 { diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go b/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go index 7f08ba6056c..c134d21bb13 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/ilaenv.go @@ -22,28 +22,28 @@ package gonum // 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 { +func (impl Implementation) Ilaenv(ispec int, name 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' + sname := name[0] == 'S' || name[0] == 'D' + cname := name[0] == 'C' || name[0] == 'Z' if !sname && !cname { - panic("lapack: bad name") + panic(badName) } - c2 := s[1:3] - c3 := s[3:6] + c2 := name[1:3] + c3 := name[3:6] c4 := c3[1:3] switch ispec { default: - panic("lapack: bad ispec") + panic(badIspec) case 1: switch c2 { default: - panic("lapack: bad function name") + panic(badName) case "GE": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": if sname { return 64 @@ -73,7 +73,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "PO": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": if sname { return 64 @@ -83,7 +83,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "SY": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": if sname { return 64 @@ -97,7 +97,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "HE": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": return 64 case "TRD": @@ -108,18 +108,18 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "OR": switch c3[0] { default: - panic("lapack: bad function name") + panic(badName) case 'G': switch c3[1:] { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 32 } case 'M': switch c3[1:] { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 32 } @@ -127,18 +127,18 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "UN": switch c3[0] { default: - panic("lapack: bad function name") + panic(badName) case 'G': switch c3[1:] { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 32 } case 'M': switch c3[1:] { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 32 } @@ -146,7 +146,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "GB": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": if sname { if n4 <= 64 { @@ -162,7 +162,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "PB": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": if sname { if n4 <= 64 { @@ -178,7 +178,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "TR": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRI": if sname { return 64 @@ -193,7 +193,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "LA": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "UUM": if sname { return 64 @@ -204,16 +204,16 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, if sname && c3 == "EBZ" { return 1 } - panic("lapack: bad function name") + panic(badName) } case 2: switch c2 { default: - panic("lapack: bad function name") + panic(badName) case "GE": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "QRF", "RQF", "LQF", "QLF": if sname { return 2 @@ -238,7 +238,7 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "SY": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "TRF": if sname { return 8 @@ -248,31 +248,31 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, if sname { return 2 } - panic("lapack: bad function name") + panic(badName) } case "HE": if c3 == "TRD" { return 2 } - panic("lapack: bad function name") + panic(badName) case "OR": if !sname { - panic("lapack: bad function name") + panic(badName) } switch c3[0] { default: - panic("lapack: bad function name") + panic(badName) case 'G': switch c4 { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 2 } case 'M': switch c4 { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 2 } @@ -280,18 +280,18 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "UN": switch c3[0] { default: - panic("lapack: bad function name") + panic(badName) case 'G': switch c4 { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 2 } case 'M': switch c4 { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 2 } @@ -300,11 +300,11 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case 3: switch c2 { default: - panic("lapack: bad function name") + panic(badName) case "GE": switch c3 { default: - panic("lapack: bad function name") + panic(badName) case "QRF", "RQF", "LQF", "QLF": if sname { return 128 @@ -325,20 +325,20 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, if sname && c3 == "TRD" { return 32 } - panic("lapack: bad function name") + panic(badName) case "HE": if c3 == "TRD" { return 32 } - panic("lapack: bad function name") + panic(badName) case "OR": switch c3[0] { default: - panic("lapack: bad function name") + panic(badName) case 'G': switch c4 { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 128 } @@ -346,11 +346,11 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, case "UN": switch c3[0] { default: - panic("lapack: bad function name") + panic(badName) case 'G': switch c4 { default: - panic("lapack: bad function name") + panic(badName) case "QR", "RQ", "LQ", "QL", "HR", "TR", "BR": return 128 } @@ -382,6 +382,6 @@ func (impl Implementation) Ilaenv(ispec int, s string, opts string, n1, n2, n3, 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) + return impl.Iparmq(ispec, name, opts, n1, n2, n3, n4) } } diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go b/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go index ea3d6dfbc10..3800f11ce18 100644 --- a/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/iparmq.go @@ -52,7 +52,7 @@ func (Implementation) Iparmq(ispec int, name, opts string, n, ilo, ihi, lwork in switch ispec { default: - panic("lapack: bad ispec") + panic(badIspec) case 12: // Matrices of order smaller than nmin get sent to Dlahqr, the @@ -82,7 +82,7 @@ func (Implementation) Iparmq(ispec int, name, opts string, n, ilo, ihi, lwork in case 16: if len(name) != 6 { - panic("lapack: bad name") + panic(badName) } const ( k22min = 14 diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go b/vendor/gonum.org/v1/gonum/lapack/gonum/lapack.go new file mode 100644 index 00000000000..434da02d2df --- /dev/null +++ b/vendor/gonum.org/v1/gonum/lapack/gonum/lapack.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 gonum + +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{} + +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 abs(a int) int { + if a < 0 { + return -a + } + return a +} + +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/vendor/gonum.org/v1/gonum/lapack/lapack.go b/vendor/gonum.org/v1/gonum/lapack/lapack.go index 5029389ce30..eef14c17a4b 100644 --- a/vendor/gonum.org/v1/gonum/lapack/lapack.go +++ b/vendor/gonum.org/v1/gonum/lapack/lapack.go @@ -6,12 +6,6 @@ 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{} @@ -35,6 +29,8 @@ type Float64 interface { 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) + Dpotri(ul blas.Uplo, n int, a []float64, lda int) (ok bool) + Dpotrs(ul blas.Uplo, n, nrhs int, a []float64, lda int, b []float64, ldb int) 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) @@ -69,22 +65,22 @@ const ( 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') + MaxAbs MatrixNorm = 'M' // max(abs(A(i,j))) + MaxColumnSum MatrixNorm = 'O' // Maximum absolute column sum (one norm) + MaxRowSum MatrixNorm = 'I' // Maximum absolute row sum (infinity norm) + Frobenius MatrixNorm = 'F' // Frobenius norm (sqrt of sum of squares) ) // MatrixType represents the kind of matrix represented in the data. type MatrixType byte const ( - General MatrixType = 'G' // A dense matrix (like blas64.General). + General MatrixType = 'G' // A general dense matrix. UpperTri MatrixType = 'U' // An upper triangular matrix. LowerTri MatrixType = 'L' // A lower triangular matrix. ) -// Pivot specifies the pivot type for plane rotations +// Pivot specifies the pivot type for plane rotations. type Pivot byte const ( @@ -93,96 +89,125 @@ const ( Bottom Pivot = 'B' ) -type DecompUpdate byte +// ApplyOrtho specifies which orthogonal matrix is applied in Dormbr. +type ApplyOrtho byte const ( - ApplyP DecompUpdate = 'P' - ApplyQ DecompUpdate = 'Q' + ApplyP ApplyOrtho = 'P' // Apply P or P^T. + ApplyQ ApplyOrtho = 'Q' // Apply Q or Q^T. +) + +// GenOrtho specifies which orthogonal matrix is generated in Dorgbr. +type GenOrtho byte + +const ( + GeneratePT GenOrtho = 'P' // Generate P^T. + GenerateQ GenOrtho = 'Q' // Generate 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 + SVDAll SVDJob = 'A' // Compute all columns of the orthogonal matrix U or V. + SVDStore SVDJob = 'S' // Compute the singular vectors and store them in the orthogonal matrix U or V. + SVDOverwrite SVDJob = 'O' // Compute the singular vectors and overwrite them on the input matrix A. + 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 + 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. +// EVComp specifies how eigenvectors are computed in Dsteqr. 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' + EVOrig EVComp = 'V' // Compute eigenvectors of the original symmetric matrix. + EVTridiag EVComp = 'I' // Compute eigenvectors of the tridiagonal matrix. + EVCompNone EVComp = 'N' // Do not compute eigenvectors. ) -// Job types for computation of eigenvectors. -type ( - EVJob byte - LeftEVJob byte - RightEVJob byte -) +// EVJob specifies whether eigenvectors are computed in Dsyev. +type EVJob 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. + EVCompute EVJob = 'V' // Compute eigenvectors. + EVNone EVJob = 'N' // Do not compute eigenvectors. ) -// Jobs for Dgebal. +// LeftEVJob specifies whether left eigenvectors are computed in Dgeev. +type LeftEVJob byte + const ( - Permute Job = 'P' - Scale Job = 'S' - PermuteScale Job = 'B' + LeftEVCompute LeftEVJob = 'V' // Compute left eigenvectors. + LeftEVNone LeftEVJob = 'N' // Do not compute left eigenvectors. ) -// Job constants for Dhseqr. +// RightEVJob specifies whether right eigenvectors are computed in Dgeev. +type RightEVJob byte + const ( - EigenvaluesOnly EVJob = 'E' - EigenvaluesAndSchur EVJob = 'S' + RightEVCompute RightEVJob = 'V' // Compute right eigenvectors. + RightEVNone RightEVJob = 'N' // Do not compute right eigenvectors. ) -// EVSide specifies what eigenvectors will be computed. +// BalanceJob specifies matrix balancing operation. +type BalanceJob byte + +const ( + Permute BalanceJob = 'P' + Scale BalanceJob = 'S' + PermuteScale BalanceJob = 'B' + BalanceNone BalanceJob = 'N' +) + +// SchurJob specifies whether the Schur form is computed in Dhseqr. +type SchurJob byte + +const ( + EigenvaluesOnly SchurJob = 'E' + EigenvaluesAndSchur SchurJob = 'S' +) + +// SchurComp specifies whether and how the Schur vectors are computed in Dhseqr. +type SchurComp byte + +const ( + SchurOrig SchurComp = 'V' // Compute Schur vectors of the original matrix. + SchurHess SchurComp = 'I' // Compute Schur vectors of the upper Hessenberg matrix. + SchurNone SchurComp = 'N' // Do not compute Schur vectors. +) + +// UpdateSchurComp specifies whether the matrix of Schur vectors is updated in Dtrexc. +type UpdateSchurComp byte + +const ( + UpdateSchur UpdateSchurComp = 'V' // Update the matrix of Schur vectors. + UpdateSchurNone UpdateSchurComp = 'N' // Do not update the matrix of Schur vectors. +) + +// EVSide specifies what eigenvectors are computed in Dtrevc3. 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. + EVRight EVSide = 'R' // Compute only right eigenvectors. + EVLeft EVSide = 'L' // Compute only left eigenvectors. + EVBoth EVSide = 'B' // Compute both right and left eigenvectors. ) -// HowMany specifies which eigenvectors will be computed. -type HowMany byte +// EVHowMany specifies which eigenvectors are computed in Dtrevc3 and how. +type EVHowMany 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. + EVAll EVHowMany = 'A' // Compute all right and/or left eigenvectors. + EVAllMulQ EVHowMany = 'B' // Compute all right and/or left eigenvectors multiplied by an input matrix. + EVSelected EVHowMany = 'S' // Compute selected right and/or left eigenvectors. ) diff --git a/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go b/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go index 259f8cc690e..208ee1f43fe 100644 --- a/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go +++ b/vendor/gonum.org/v1/gonum/lapack/lapack64/lapack64.go @@ -19,6 +19,13 @@ func Use(l lapack.Float64) { lapack64 = l } +func max(a, b int) int { + if a > b { + return a + } + return b +} + // Potrf computes the Cholesky factorization of a. // The factorization has the form // A = U^T * U if a.Uplo == blas.Upper, or @@ -28,7 +35,7 @@ func Use(l lapack.Float64) { // 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) + ok = lapack64.Dpotrf(a.Uplo, a.N, a.Data, max(1, a.Stride)) t.Uplo = a.Uplo t.N = a.N t.Data = a.Data @@ -37,6 +44,35 @@ func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) { return } +// Potri computes the inverse of a real symmetric positive definite matrix A +// using its Cholesky factorization. +// +// On entry, t contains the triangular factor U or L from the Cholesky +// factorization A = U^T*U or A = L*L^T, as computed by Potrf. +// +// On return, the upper or lower triangle of the (symmetric) inverse of A is +// stored in t, overwriting the input factor U or L, and also returned in a. The +// underlying data between a and t is shared. +// +// The returned bool indicates whether the inverse was computed successfully. +func Potri(t blas64.Triangular) (a blas64.Symmetric, ok bool) { + ok = lapack64.Dpotri(t.Uplo, t.N, t.Data, max(1, t.Stride)) + a.Uplo = t.Uplo + a.N = t.N + a.Data = t.Data + a.Stride = t.Stride + return +} + +// Potrs solves a system of n linear equations A*X = B where A is an n×n +// symmetric positive definite matrix and B is an n×nrhs matrix, using the +// Cholesky factorization A = U^T*U or A = L*L^T. t contains the corresponding +// triangular factor as returned by Potrf. On entry, B contains the right-hand +// side matrix B, on return it contains the solution matrix X. +func Potrs(t blas64.Triangular, b blas64.General) { + lapack64.Dpotrs(t.Uplo, t.N, b.Cols, t.Data, max(1, t.Stride), b.Data, max(1, b.Stride)) +} + // 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. @@ -49,7 +85,7 @@ func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) { // // 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) + return lapack64.Dgecon(norm, a.Cols, a.Data, max(1, a.Stride), anorm, work, iwork) } // Gels finds a minimum-norm solution based on the matrices A and B using the @@ -82,7 +118,7 @@ func Gecon(norm lapack.MatrixNorm, a blas64.General, anorm float64, work []float // 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) + return lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride), work, lwork) } // Geqrf computes the QR factorization of the m×n matrix A using a blocked @@ -108,7 +144,7 @@ func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float // 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) + lapack64.Dgeqrf(a.Rows, a.Cols, a.Data, max(1, a.Stride), tau, work, lwork) } // Gelqf computes the LQ factorization of the m×n matrix A using a blocked @@ -128,7 +164,7 @@ func Geqrf(a blas64.General, tau, work []float64, lwork int) { // 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) + lapack64.Dgelqf(a.Rows, a.Cols, a.Data, max(1, a.Stride), tau, work, lwork) } // Gesvd computes the singular value decomposition of the input matrix A. @@ -143,7 +179,7 @@ func Gelqf(a blas64.General, tau, work []float64, lwork int) { // 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.SVDStore 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 @@ -157,12 +193,12 @@ func Gelqf(a blas64.General, tau, work []float64, lwork int) { // 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 +// jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDStore 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 +// jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDStore vt is // of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is // not used. // @@ -174,7 +210,7 @@ func Gelqf(a blas64.General, tau, work []float64, lwork int) { // // 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) + return lapack64.Dgesvd(jobU, jobVT, a.Rows, a.Cols, a.Data, max(1, a.Stride), s, u.Data, max(1, u.Stride), vt.Data, max(1, vt.Stride), work, lwork) } // Getrf computes the LU decomposition of the m×n matrix A. @@ -195,7 +231,7 @@ func Gesvd(jobU, jobVT lapack.SVDJob, a, u, vt blas64.General, s, work []float64 // 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) + return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, max(1, a.Stride), ipiv) } // Getri computes the inverse of the matrix A using the LU factorization computed @@ -211,7 +247,7 @@ func Getrf(a blas64.General, ipiv []int) bool { // 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) + return lapack64.Dgetri(a.Cols, a.Data, max(1, a.Stride), ipiv, work, lwork) } // Getrs solves a system of equations using an LU factorization. @@ -226,7 +262,7 @@ func Getri(a blas64.General, ipiv []int, work []float64, lwork int) (ok bool) { // 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) + lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, max(1, a.Stride), ipiv, b.Data, max(1, b.Stride)) } // Ggsvd3 computes the generalized singular value decomposition (GSVD) @@ -326,7 +362,7 @@ func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) // 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) + return lapack64.Dggsvd3(jobU, jobV, jobQ, a.Rows, a.Cols, b.Rows, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride), alpha, beta, u.Data, max(1, u.Stride), v.Data, max(1, v.Stride), q.Data, max(1, q.Stride), work, lwork, iwork) } // Lange computes the matrix norm of the general m×n matrix A. The input norm @@ -338,7 +374,7 @@ func Ggsvd3(jobU, jobV, jobQ lapack.GSVDJob, a, b blas64.General, alpha, beta [] // 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) + return lapack64.Dlange(norm, a.Rows, a.Cols, a.Data, max(1, a.Stride), work) } // Lansy computes the specified norm of an n×n symmetric matrix. If @@ -346,14 +382,14 @@ func Lange(norm lapack.MatrixNorm, a blas64.General, work []float64) float64 { // 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) + return lapack64.Dlansy(norm, a.Uplo, a.N, a.Data, max(1, 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) + return lapack64.Dlantr(norm, a.Uplo, a.Diag, a.N, a.N, a.Data, max(1, a.Stride), work) } // Lapmt rearranges the columns of the m×n matrix X as specified by the @@ -369,7 +405,7 @@ func Lantr(norm lapack.MatrixNorm, a blas64.Triangular, work []float64) float64 // // 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) + lapack64.Dlapmt(forward, x.Rows, x.Cols, x.Data, max(1, x.Stride), k) } // Ormlq multiplies the matrix C by the othogonal matrix Q defined by @@ -391,7 +427,7 @@ func Lapmt(forward bool, x blas64.General, k []int) { // 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) + lapack64.Dormlq(side, trans, c.Rows, c.Cols, a.Rows, a.Data, max(1, a.Stride), tau, c.Data, max(1, c.Stride), work, lwork) } // Ormqr multiplies an m×n matrix C by an orthogonal matrix Q as @@ -422,7 +458,7 @@ func Ormlq(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64 // 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) + lapack64.Dormqr(side, trans, c.Rows, c.Cols, a.Cols, a.Data, max(1, a.Stride), tau, c.Data, max(1, c.Stride), work, lwork) } // Pocon estimates the reciprocal of the condition number of a positive-definite @@ -435,7 +471,7 @@ func Ormqr(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64 // // 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) + return lapack64.Dpocon(a.Uplo, a.N, a.Data, max(1, a.Stride), anorm, work, iwork) } // Syev computes all eigenvalues and, optionally, the eigenvectors of a real @@ -445,16 +481,16 @@ func Pocon(a blas64.Symmetric, anorm float64, work []float64, iwork []int) float // 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. +// portion specified by uplo. If jobz == lapack.EVCompute, a contains the +// orthonormal eigenvectors of A on exit, otherwise jobz must be lapack.EVNone +// and 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) + return lapack64.Dsyev(jobz, a.Uplo, a.N, a.Data, max(1, a.Stride), w, work, lwork) } // Trcon estimates the reciprocal of the condition number of a triangular matrix A. @@ -464,7 +500,7 @@ func Syev(jobz lapack.EVJob, a blas64.Symmetric, w, work []float64, lwork int) ( // // 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) + return lapack64.Dtrcon(norm, a.Uplo, a.Diag, a.N, a.Data, max(1, a.Stride), work, iwork) } // Trtri computes the inverse of a triangular matrix, storing the result in place @@ -473,13 +509,13 @@ func Trcon(norm lapack.MatrixNorm, a blas64.Triangular, work []float64, iwork [] // 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) + return lapack64.Dtrtri(a.Uplo, a.Diag, a.N, a.Data, max(1, 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) + return lapack64.Dtrtrs(a.Uplo, trans, a.Diag, a.N, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride)) } // Geev computes the eigenvalues and, optionally, the left and/or right @@ -506,10 +542,10 @@ func Trtrs(trans blas.Transpose, a blas64.Triangular, b blas64.General) (ok bool // 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. +// Left eigenvectors will be computed only if jobvl == lapack.LeftEVCompute, +// otherwise jobvl must be lapack.LeftEVNone. +// Right eigenvectors will be computed only if jobvr == lapack.RightEVCompute, +// otherwise jobvr must be lapack.RightEVNone. // For other values of jobvl and jobvr Geev will panic. // // On return, wr and wi will contain the real and imaginary parts, respectively, @@ -535,11 +571,11 @@ func Geev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, a blas64.General, wr, if a.Cols != n { panic("lapack64: matrix not square") } - if jobvl == lapack.ComputeLeftEV && (vl.Rows != n || vl.Cols != n) { + if jobvl == lapack.LeftEVCompute && (vl.Rows != n || vl.Cols != n) { panic("lapack64: bad size of VL") } - if jobvr == lapack.ComputeRightEV && (vr.Rows != n || vr.Cols != n) { + if jobvr == lapack.RightEVCompute && (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) + return lapack64.Dgeev(jobvl, jobvr, n, a.Data, max(1, a.Stride), wr, wi, vl.Data, max(1, vl.Stride), vr.Data, max(1, vr.Stride), work, lwork) } diff --git a/vendor/gonum.org/v1/gonum/mat/BUILD b/vendor/gonum.org/v1/gonum/mat/BUILD index 48ff4d1af7a..799c6d0c2f7 100644 --- a/vendor/gonum.org/v1/gonum/mat/BUILD +++ b/vendor/gonum.org/v1/gonum/mat/BUILD @@ -4,11 +4,13 @@ go_library( name = "go_default_library", srcs = [ "band.go", + "cdense.go", "cholesky.go", "cmatrix.go", "consts.go", "dense.go", "dense_arithmetic.go", + "diagonal.go", "doc.go", "eigen.go", "errors.go", @@ -31,6 +33,7 @@ go_library( "symband.go", "symmetric.go", "triangular.go", + "triband.go", "vector.go", ], importmap = "k8s.io/kubernetes/vendor/gonum.org/v1/gonum/mat", @@ -39,6 +42,7 @@ go_library( deps = [ "//vendor/gonum.org/v1/gonum/blas:go_default_library", "//vendor/gonum.org/v1/gonum/blas/blas64:go_default_library", + "//vendor/gonum.org/v1/gonum/blas/cblas128:go_default_library", "//vendor/gonum.org/v1/gonum/floats:go_default_library", "//vendor/gonum.org/v1/gonum/internal/asm/f64:go_default_library", "//vendor/gonum.org/v1/gonum/lapack:go_default_library", diff --git a/vendor/gonum.org/v1/gonum/mat/band.go b/vendor/gonum.org/v1/gonum/mat/band.go index d196a5aef24..72ebefddd1d 100644 --- a/vendor/gonum.org/v1/gonum/mat/band.go +++ b/vendor/gonum.org/v1/gonum/mat/band.go @@ -107,6 +107,7 @@ func (t TransposeBand) UntransposeBand() Banded { // BandDense will be reflected in data. If neither of these is true, NewBandDense // will panic. kl must be at least zero and less r, and ku must be at least zero and // less than c, otherwise NewBandDense will panic. +// NewBandDense will panic if either r or c is zero. // // The data must be arranged in row-major order constructed by removing the zeros // from the rows outside the band and aligning the diagonals. For example, the matrix @@ -126,7 +127,10 @@ func (t TransposeBand) UntransposeBand() Banded { // which is passed to NewBandDense as []float64{*, 1, 2, 3, 4, ...} with kl=1 and ku=2. // Only the values in the band portion of the matrix are used. func NewBandDense(r, c, kl, ku int, data []float64) *BandDense { - if r < 0 || c < 0 || kl < 0 || ku < 0 { + if r <= 0 || c <= 0 || kl < 0 || ku < 0 { + if r == 0 || c == 0 { + panic(ErrZeroLength) + } panic("mat: negative dimension") } if kl+1 > r || ku+1 > c { @@ -184,6 +188,25 @@ func (b *BandDense) RawBand() blas64.Band { return b.mat } +// SetRawBand sets the underlying blas64.Band used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in the input. +func (b *BandDense) SetRawBand(mat blas64.Band) { + b.mat = mat +} + +// DiagView returns the diagonal as a matrix backed by the original data. +func (b *BandDense) DiagView() Diagonal { + n := min(b.mat.Rows, b.mat.Cols) + return &DiagDense{ + mat: blas64.Vector{ + N: n, + Inc: b.mat.Stride, + Data: b.mat.Data[b.mat.KL : (n-1)*b.mat.Stride+b.mat.KL+1], + }, + } +} + // DoNonZero calls the function fn for each of the non-zero elements of b. The function fn // takes a row/column index and the element value of b at (i, j). func (b *BandDense) DoNonZero(fn func(i, j int, v float64)) { @@ -226,3 +249,15 @@ func (b *BandDense) DoColNonZero(j int, fn func(i, j int, v float64)) { } } } + +// Zero sets all of the matrix elements to zero. +func (b *BandDense) Zero() { + m := b.mat.Rows + kL := b.mat.KL + nCol := b.mat.KU + 1 + kL + for i := 0; i < m; i++ { + l := max(0, kL-i) + u := min(nCol, m+kL-i) + zero(b.mat.Data[i*b.mat.Stride+l : i*b.mat.Stride+u]) + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/cdense.go b/vendor/gonum.org/v1/gonum/mat/cdense.go new file mode 100644 index 00000000000..9c29d1afd19 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/cdense.go @@ -0,0 +1,168 @@ +// Copyright ©2019 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat + +import "gonum.org/v1/gonum/blas/cblas128" + +// Dense is a dense matrix representation with complex data. +type CDense struct { + mat cblas128.General + + capRows, capCols int +} + +// Dims returns the number of rows and columns in the matrix. +func (m *CDense) Dims() (r, c int) { + return m.mat.Rows, m.mat.Cols +} + +// H performs an implicit conjugate transpose by returning the receiver inside a +// Conjugate. +func (m *CDense) H() CMatrix { + return Conjugate{m} +} + +// NewCDense creates a new complex 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 CDense will be reflected in data. +// If neither of these is true, NewCDense will panic. +// NewCDense will panic if either r or c is zero. +// +// 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 NewCDense(r, c int, data []complex128) *CDense { + if r <= 0 || c <= 0 { + if r == 0 || c == 0 { + panic(ErrZeroLength) + } + panic("mat: negative dimension") + } + if data != nil && r*c != len(data) { + panic(ErrShape) + } + if data == nil { + data = make([]complex128, r*c) + } + return &CDense{ + mat: cblas128.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 *CDense) reuseAs(r, c int) { + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat.Error. + panic("mat: caps not correctly set") + } + if r == 0 || c == 0 { + panic(ErrZeroLength) + } + if m.IsZero() { + m.mat = cblas128.General{ + Rows: r, + Cols: c, + Stride: c, + Data: useC(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + return + } + if r != m.mat.Rows || c != m.mat.Cols { + panic(ErrShape) + } +} + +func (m *CDense) reuseAsZeroed(r, c int) { + // This must be kept in-sync with reuseAs. + if m.mat.Rows > m.capRows || m.mat.Cols > m.capCols { + // Panic as a string, not a mat.Error. + panic("mat: caps not correctly set") + } + if r == 0 || c == 0 { + panic(ErrZeroLength) + } + if m.IsZero() { + m.mat = cblas128.General{ + Rows: r, + Cols: c, + Stride: c, + Data: useZeroedC(m.mat.Data, r*c), + } + m.capRows = r + m.capCols = c + return + } + if r != m.mat.Rows || c != m.mat.Cols { + panic(ErrShape) + } + m.Zero() +} + +// 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 *CDense) 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] +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the +// receiver for size-restricted operations. CDense matrices can be zeroed using Reset. +func (m *CDense) IsZero() bool { + // It must be the case that m.Dims() returns + // zeros in this case. See comment in Reset(). + return m.mat.Stride == 0 +} + +// Zero sets all of the matrix elements to zero. +func (m *CDense) Zero() { + r := m.mat.Rows + c := m.mat.Cols + for i := 0; i < r; i++ { + zeroC(m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]) + } +} + +// 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 VecDense, with a non-unitary increment, Copy will +// panic. +// +// See the Copier interface for more information. +func (m *CDense) Copy(a CMatrix) (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 + } + // TODO(btracey): Check for overlap when complex version exists. + // TODO(btracey): Add fast-paths. + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + m.set(i, j, a.At(i, j)) + } + } + return r, c +} diff --git a/vendor/gonum.org/v1/gonum/mat/cholesky.go b/vendor/gonum.org/v1/gonum/mat/cholesky.go index 399c8114137..bee438538f3 100644 --- a/vendor/gonum.org/v1/gonum/mat/cholesky.go +++ b/vendor/gonum.org/v1/gonum/mat/cholesky.go @@ -17,8 +17,21 @@ const ( badCholesky = "mat: invalid Cholesky factorization" ) -// Cholesky is a type for creating and using the Cholesky factorization of a -// symmetric positive definite matrix. +var ( + _ Matrix = (*Cholesky)(nil) + _ Symmetric = (*Cholesky)(nil) +) + +// Cholesky is a symmetric positive definite matrix represented by its +// Cholesky decomposition. +// +// The decomposition can be constructed using the Factorize method. The +// factorization itself can be extracted using the UTo or LTo methods, and the +// original symmetric matrix can be recovered with ToSym. +// +// Note that this matrix representation is useful for certain operations, in +// particular finding solutions to linear equations. It is very inefficient +// at other operations, in particular At is slow. // // 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 @@ -58,8 +71,52 @@ func (c *Cholesky) updateCond(norm float64) { c.cond = 1 / v } +// Dims returns the dimensions of the matrix. +func (ch *Cholesky) Dims() (r, c int) { + if !ch.valid() { + panic(badCholesky) + } + r, c = ch.chol.Dims() + return r, c +} + +// At returns the element at row i, column j. +func (c *Cholesky) At(i, j int) float64 { + if !c.valid() { + panic(badCholesky) + } + n := c.Symmetric() + if uint(i) >= uint(n) { + panic(ErrRowAccess) + } + if uint(j) >= uint(n) { + panic(ErrColAccess) + } + + var val float64 + for k := 0; k <= min(i, j); k++ { + val += c.chol.at(k, i) * c.chol.at(k, j) + } + return val +} + +// T returns the the receiver, the transpose of a symmetric matrix. +func (c *Cholesky) T() Matrix { + return c +} + +// Symmetric implements the Symmetric interface and returns the number of rows +// in the matrix (this is also the number of columns). +func (c *Cholesky) Symmetric() int { + r, _ := c.chol.Dims() + return r +} + // Cond returns the condition number of the factorized matrix. func (c *Cholesky) Cond() float64 { + if !c.valid() { + panic(badCholesky) + } return c.cond } @@ -121,7 +178,7 @@ func (c *Cholesky) Clone(chol *Cholesky) { if !chol.valid() { panic(badCholesky) } - n := chol.Size() + n := chol.Symmetric() if c.chol == nil { c.chol = NewTriDense(n, Upper, nil) } else { @@ -131,14 +188,6 @@ func (c *Cholesky) Clone(chol *Cholesky) { 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() { @@ -159,9 +208,9 @@ func (c *Cholesky) LogDet() float64 { return det } -// Solve finds the matrix x that solves A * X = B where A is represented -// by the Cholesky decomposition, placing the result in x. -func (c *Cholesky) Solve(x *Dense, b Matrix) error { +// SolveTo finds the matrix X that solves A * X = B where A is represented +// by the Cholesky decomposition. The result is stored in-place into dst. +func (c *Cholesky) SolveTo(dst *Dense, b Matrix) error { if !c.valid() { panic(badCholesky) } @@ -171,21 +220,21 @@ func (c *Cholesky) Solve(x *Dense, b Matrix) error { panic(ErrShape) } - x.reuseAs(bm, bn) - if b != x { - x.Copy(b) + dst.reuseAs(bm, bn) + if b != dst { + dst.Copy(b) } - blas64.Trsm(blas.Left, blas.Trans, 1, c.chol.mat, x.mat) - blas64.Trsm(blas.Left, blas.NoTrans, 1, c.chol.mat, x.mat) + lapack64.Potrs(c.chol.mat, dst.mat) if c.cond > ConditionTolerance { return Condition(c.cond) } return nil } -// SolveChol finds the matrix x that solves A * X = B where A and B are represented -// by their Cholesky decompositions a and b, placing the result in x. -func (a *Cholesky) SolveChol(x *Dense, b *Cholesky) error { +// SolveCholTo finds the matrix X that solves A * X = B where A and B are represented +// by their Cholesky decompositions a and b. The result is stored in-place into +// dst. +func (a *Cholesky) SolveCholTo(dst *Dense, b *Cholesky) error { if !a.valid() || !b.valid() { panic(badCholesky) } @@ -194,20 +243,21 @@ func (a *Cholesky) SolveChol(x *Dense, b *Cholesky) error { panic(ErrShape) } - x.reuseAsZeroed(bn, bn) - x.Copy(b.chol.T()) - blas64.Trsm(blas.Left, blas.Trans, 1, a.chol.mat, x.mat) - blas64.Trsm(blas.Left, blas.NoTrans, 1, a.chol.mat, x.mat) - blas64.Trmm(blas.Right, blas.NoTrans, 1, b.chol.mat, x.mat) + dst.reuseAsZeroed(bn, bn) + dst.Copy(b.chol.T()) + blas64.Trsm(blas.Left, blas.Trans, 1, a.chol.mat, dst.mat) + blas64.Trsm(blas.Left, blas.NoTrans, 1, a.chol.mat, dst.mat) + blas64.Trmm(blas.Right, blas.NoTrans, 1, b.chol.mat, dst.mat) if a.cond > ConditionTolerance { return Condition(a.cond) } return nil } -// SolveVec finds the vector x that solves A * x = b where A is represented -// by the Cholesky decomposition, placing the result in x. -func (c *Cholesky) SolveVec(x *VecDense, b Vector) error { +// SolveVecTo finds the vector X that solves A * x = b where A is represented +// by the Cholesky decomposition. The result is stored in-place into +// dst. +func (c *Cholesky) SolveVecTo(dst *VecDense, b Vector) error { if !c.valid() { panic(badCholesky) } @@ -217,19 +267,18 @@ func (c *Cholesky) SolveVec(x *VecDense, b Vector) error { } switch rv := b.(type) { default: - x.reuseAs(n) - return c.Solve(x.asDense(), b) + dst.reuseAs(n) + return c.SolveTo(dst.asDense(), b) case RawVectorer: bmat := rv.RawVector() - if x != b { - x.checkOverlap(bmat) + if dst != b { + dst.checkOverlap(bmat) } - x.reuseAs(n) - if x != b { - x.CopyVec(b) + dst.reuseAs(n) + if dst != b { + dst.CopyVec(b) } - blas64.Trsv(blas.Trans, c.chol.mat, x.mat) - blas64.Trsv(blas.NoTrans, c.chol.mat, x.mat) + lapack64.Potrs(c.chol.mat, dst.asGeneral()) if c.cond > ConditionTolerance { return Condition(c.cond) } @@ -289,11 +338,34 @@ func (c *Cholesky) ToSym(dst *SymDense) *SymDense { } n := c.chol.mat.N if dst == nil { - dst = NewSymDense(n, make([]float64, n*n)) + dst = NewSymDense(n, nil) } else { dst.reuseAs(n) } - dst.SymOuterK(1, c.chol.T()) + // Create a TriDense representing the Cholesky factor U with dst's + // backing slice. + // Operations on u are reflected in s. + u := &TriDense{ + mat: blas64.Triangular{ + Uplo: blas.Upper, + Diag: blas.NonUnit, + N: n, + Data: dst.mat.Data, + Stride: dst.mat.Stride, + }, + cap: n, + } + u.Copy(c.chol) + // Compute the product U^T*U using the algorithm from LAPACK/TESTING/LIN/dpot01.f + a := u.mat.Data + lda := u.mat.Stride + bi := blas64.Implementation() + for k := n - 1; k >= 0; k-- { + a[k*lda+k] = bi.Ddot(k+1, a[k:], lda, a[k:], lda) + if k > 0 { + bi.Dtrmv(blas.Upper, blas.Trans, blas.NonUnit, k, a, lda, a[k:], lda) + } + } return dst } @@ -306,18 +378,30 @@ func (c *Cholesky) InverseTo(s *SymDense) error { if !c.valid() { panic(badCholesky) } - // TODO(btracey): Replace this code with a direct call to Dpotri when it - // is available. s.reuseAs(c.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(c.chol) - s.SymOuterK(1, &t) - return err + // Create a TriDense representing the Cholesky factor U with the backing + // slice from s. + // Operations on u are reflected in s. + u := &TriDense{ + mat: blas64.Triangular{ + Uplo: blas.Upper, + Diag: blas.NonUnit, + N: s.mat.N, + Data: s.mat.Data, + Stride: s.mat.Stride, + }, + cap: s.mat.N, + } + u.Copy(c.chol) + + _, ok := lapack64.Potri(u.mat) + if !ok { + return Condition(math.Inf(1)) + } + if c.cond > ConditionTolerance { + return Condition(c.cond) + } + return nil } // Scale multiplies the original matrix A by a positive constant using @@ -327,7 +411,7 @@ func (c *Cholesky) InverseTo(s *SymDense) error { // the updated factorization is // U'^T * U' = f A = A' // Scale panics if the constant is non-positive, or if the receiver is non-zero -// and is of a different Size from the input. +// and is of a different size from the input. func (c *Cholesky) Scale(f float64, orig *Cholesky) { if !orig.valid() { panic(badCholesky) @@ -335,7 +419,7 @@ func (c *Cholesky) Scale(f float64, orig *Cholesky) { if f <= 0 { panic("cholesky: scaling by a non-positive constant") } - n := orig.Size() + n := orig.Symmetric() if c.chol == nil { c.chol = NewTriDense(n, Upper, nil) } else if c.chol.mat.N != n { @@ -354,10 +438,11 @@ func (c *Cholesky) Scale(f float64, orig *Cholesky) { // that k > w' A^-1 w. If this condition does not hold then ExtendVecSym will // return false and the receiver will not be updated. // -// ExtendVecSym will panic if v.Len() != a.Size()+1 or if a does not contain +// ExtendVecSym will panic if v.Len() != a.Symmetric()+1 or if a does not contain // a valid decomposition. -func (chol *Cholesky) ExtendVecSym(a *Cholesky, v Vector) (ok bool) { - n := a.Size() +func (c *Cholesky) ExtendVecSym(a *Cholesky, v Vector) (ok bool) { + n := a.Symmetric() + if v.Len() != n+1 { panic(badSliceLength) } @@ -389,10 +474,10 @@ func (chol *Cholesky) ExtendVecSym(a *Cholesky, v Vector) (ok bool) { } k := v.At(n, 0) - c := NewVecDense(n, nil) - c.SolveVec(a.chol.T(), w) + var t VecDense + t.SolveVec(a.chol.T(), w) - dot := Dot(c, c) + dot := Dot(&t, &t) if dot >= k { return false } @@ -401,11 +486,11 @@ func (chol *Cholesky) ExtendVecSym(a *Cholesky, v Vector) (ok bool) { newU := NewTriDense(n+1, Upper, nil) newU.Copy(a.chol) for i := 0; i < n; i++ { - newU.SetTri(i, n, c.At(i, 0)) + newU.SetTri(i, n, t.At(i, 0)) } newU.SetTri(n, n, d) - chol.chol = newU - chol.updateCond(-1) + c.chol = newU + c.updateCond(-1) return true } @@ -427,7 +512,7 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) if !orig.valid() { panic(badCholesky) } - n := orig.Size() + n := orig.Symmetric() if r, c := x.Dims(); r != n || c != 1 { panic(ErrShape) } @@ -480,12 +565,12 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) tmp.CopyVec(x) xmat = tmp.RawVector() } - blas64.Copy(n, xmat, blas64.Vector{1, work}) + blas64.Copy(xmat, blas64.Vector{N: n, Data: work, Inc: 1}) if alpha > 0 { // Compute rank-1 update. if alpha != 1 { - blas64.Scal(n, math.Sqrt(alpha), blas64.Vector{1, work}) + blas64.Scal(math.Sqrt(alpha), blas64.Vector{N: n, Data: work, Inc: 1}) } umat := c.chol.mat stride := umat.Stride @@ -505,9 +590,9 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) // 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]}, + blas64.Rot( + blas64.Vector{N: n - i - 1, Data: umat.Data[i*stride+i+1 : i*stride+n], Inc: 1}, + blas64.Vector{N: n - i - 1, Data: work[i+1 : n], Inc: 1}, c, s) } } @@ -518,7 +603,7 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) // Compute rank-1 downdate. alpha = math.Sqrt(-alpha) if alpha != 1 { - blas64.Scal(n, alpha, blas64.Vector{1, work}) + blas64.Scal(alpha, blas64.Vector{N: n, Data: work, Inc: 1}) } // Solve U^T * p = x storing the result into work. ok = lapack64.Trtrs(blas.Trans, c.chol.RawTriangular(), blas64.General{ @@ -532,7 +617,7 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) // the factorization is valid. panic(badCholesky) } - norm := blas64.Nrm2(n, blas64.Vector{1, work}) + norm := blas64.Nrm2(blas64.Vector{N: n, Data: work, Inc: 1}) if norm >= 1 { // The updated matrix is not positive definite. return false @@ -559,7 +644,10 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) // 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]) + blas64.Rot( + blas64.Vector{N: n - i, Data: work[i:n], Inc: 1}, + blas64.Vector{N: n - i, Data: umat.Data[i*stride+i : i*stride+n], Inc: 1}, + cos[i], sin[i]) if umat.Data[i*stride+i] == 0 { // The matrix is singular (may rarely happen due to // floating-point effects?). @@ -569,7 +657,7 @@ func (c *Cholesky) SymRankOne(orig *Cholesky, alpha float64, x Vector) (ok bool) // 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]}) + blas64.Scal(-1, blas64.Vector{N: n - i, Data: umat.Data[i*stride+i : i*stride+n], Inc: 1}) } } if ok { diff --git a/vendor/gonum.org/v1/gonum/mat/cmatrix.go b/vendor/gonum.org/v1/gonum/mat/cmatrix.go index fa8e135b363..6219c28aaa4 100644 --- a/vendor/gonum.org/v1/gonum/mat/cmatrix.go +++ b/vendor/gonum.org/v1/gonum/mat/cmatrix.go @@ -4,6 +4,13 @@ package mat +import ( + "math" + "math/cmplx" + + "gonum.org/v1/gonum/floats" +) + // CMatrix is the basic matrix interface type for complex matrices. type CMatrix interface { // Dims returns the dimensions of a Matrix. @@ -32,11 +39,11 @@ type Conjugate struct { CMatrix CMatrix } -// 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. +// At returns the value of the element at row i and column j of the conjugate +// transposed matrix, that is, row j and column i of the Matrix field. func (t Conjugate) At(i, j int) complex128 { z := t.CMatrix.At(j, i) - return complex(real(z), -imag(z)) + return cmplx.Conj(z) } // Dims returns the dimensions of the transposed matrix. The number of rows returned @@ -69,3 +76,135 @@ type Unconjugator interface { // conjugate transpose. Unconjugate() CMatrix } + +// useC returns a complex128 slice with l elements, using c if it +// has the necessary capacity, otherwise creating a new slice. +func useC(c []complex128, l int) []complex128 { + if l <= cap(c) { + return c[:l] + } + return make([]complex128, l) +} + +// useZeroedC returns a complex128 slice with l elements, using c if it +// has the necessary capacity, otherwise creating a new slice. The +// elements of the returned slice are guaranteed to be zero. +func useZeroedC(c []complex128, l int) []complex128 { + if l <= cap(c) { + c = c[:l] + zeroC(c) + return c + } + return make([]complex128, l) +} + +// zeroC zeros the given slice's elements. +func zeroC(c []complex128) { + for i := range c { + c[i] = 0 + } +} + +// unconjugate unconjugates a matrix if applicable. If a is an Unconjugator, then +// unconjugate returns the underlying matrix and true. If it is not, then it returns +// the input matrix and false. +func unconjugate(a CMatrix) (CMatrix, bool) { + if ut, ok := a.(Unconjugator); ok { + return ut.Unconjugate(), true + } + return a, false +} + +// CEqual returns whether the matrices a and b have the same size +// and are element-wise equal. +func CEqual(a, b CMatrix) bool { + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + return false + } + // TODO(btracey): Add in fast-paths. + 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 +} + +// CEqualApprox 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 CEqualApprox(a, b CMatrix, epsilon float64) bool { + // TODO(btracey): + ar, ac := a.Dims() + br, bc := b.Dims() + if ar != br || ac != bc { + return false + } + for i := 0; i < ar; i++ { + for j := 0; j < ac; j++ { + if !cEqualWithinAbsOrRel(a.At(i, j), b.At(i, j), epsilon, epsilon) { + return false + } + } + } + return true +} + +// TODO(btracey): Move these into a cmplxs if/when we have one. + +func cEqualWithinAbsOrRel(a, b complex128, absTol, relTol float64) bool { + if cEqualWithinAbs(a, b, absTol) { + return true + } + return cEqualWithinRel(a, b, relTol) +} + +// cEqualWithinAbs returns true if a and b have an absolute +// difference of less than tol. +func cEqualWithinAbs(a, b complex128, tol float64) bool { + return a == b || cmplx.Abs(a-b) <= tol +} + +const minNormalFloat64 = 2.2250738585072014e-308 + +// cEqualWithinRel returns true if the difference between a and b +// is not greater than tol times the greater value. +func cEqualWithinRel(a, b complex128, tol float64) bool { + if a == b { + return true + } + if cmplx.IsNaN(a) || cmplx.IsNaN(b) { + return false + } + // Cannot play the same trick as in floats because there are multiple + // possible infinities. + if cmplx.IsInf(a) { + if !cmplx.IsInf(b) { + return false + } + ra := real(a) + if math.IsInf(ra, 0) { + if ra == real(b) { + return floats.EqualWithinRel(imag(a), imag(b), tol) + } + return false + } + if imag(a) == imag(b) { + return floats.EqualWithinRel(ra, real(b), tol) + } + return false + } + if cmplx.IsInf(b) { + return false + } + + delta := cmplx.Abs(a - b) + if delta <= minNormalFloat64 { + return delta <= tol*minNormalFloat64 + } + return delta/math.Max(cmplx.Abs(a), cmplx.Abs(b)) <= tol +} diff --git a/vendor/gonum.org/v1/gonum/mat/consts.go b/vendor/gonum.org/v1/gonum/mat/consts.go index a7b6370d53d..3de3f5bf47d 100644 --- a/vendor/gonum.org/v1/gonum/mat/consts.go +++ b/vendor/gonum.org/v1/gonum/mat/consts.go @@ -13,42 +13,3 @@ const ( // 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/vendor/gonum.org/v1/gonum/mat/dense.go b/vendor/gonum.org/v1/gonum/mat/dense.go index fbcac75664c..87b1105cad2 100644 --- a/vendor/gonum.org/v1/gonum/mat/dense.go +++ b/vendor/gonum.org/v1/gonum/mat/dense.go @@ -38,11 +38,15 @@ type Dense struct { // 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. +// NewDense will panic if either r or c is zero. // // 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 r < 0 || c < 0 { + if r <= 0 || c <= 0 { + if r == 0 || c == 0 { + panic(ErrZeroLength) + } panic("mat: negative dimension") } if data != nil && r*c != len(data) { @@ -118,21 +122,18 @@ func (m *Dense) reuseAsZeroed(r, c int) { if r != m.mat.Rows || c != m.mat.Cols { panic(ErrShape) } + m.Zero() +} + +// Zero sets all of the matrix elements to zero. +func (m *Dense) Zero() { + r := m.mat.Rows + c := m.mat.Cols 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. @@ -232,9 +233,9 @@ func (m *Dense) SetCol(j int, src []float64) { panic(ErrColLength) } - blas64.Copy(m.mat.Rows, - blas64.Vector{Inc: 1, Data: src}, - blas64.Vector{Inc: m.mat.Stride, Data: m.mat.Data[j:]}, + blas64.Copy( + blas64.Vector{N: m.mat.Rows, Inc: 1, Data: src}, + blas64.Vector{N: m.mat.Rows, Inc: m.mat.Stride, Data: m.mat.Data[j:]}, ) } @@ -274,6 +275,18 @@ func (m *Dense) rawRowView(i int) []float64 { return m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+m.mat.Cols] } +// DiagView returns the diagonal as a matrix backed by the original data. +func (m *Dense) DiagView() Diagonal { + n := min(m.mat.Rows, m.mat.Cols) + return &DiagDense{ + mat: blas64.Vector{ + N: n, + Inc: m.mat.Stride + 1, + Data: m.mat.Data[:(n-1)*m.mat.Stride+n], + }, + } +} + // Slice returns a new Matrix that shares backing data with the receiver. // The returned matrix starts at {i,j} of the receiver and extends k-i rows // and l-j columns. The final row in the resulting matrix is k-1 and the @@ -282,7 +295,10 @@ func (m *Dense) rawRowView(i int) []float64 { // of the receiver. func (m *Dense) Slice(i, k, j, l int) Matrix { mr, mc := m.Caps() - if i < 0 || mr <= i || j < 0 || mc <= j || k <= i || mr < k || l <= j || mc < l { + if i < 0 || mr <= i || j < 0 || mc <= j || k < i || mr < k || l < j || mc < l { + if i == k || j == l { + panic(ErrZeroLength) + } panic(ErrIndexOutOfRange) } t := *m @@ -380,9 +396,8 @@ func (m *Dense) Clone(a Matrix) { 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]}) + blas64.Copy(blas64.Vector{N: c, Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, + blas64.Vector{N: c, Inc: 1, Data: mat.Data[i*c : (i+1)*c]}) } } else { for i := 0; i < r; i++ { @@ -391,10 +406,9 @@ func (m *Dense) Clone(a Matrix) { } case *VecDense: 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}) + mat.Data = make([]float64, aU.mat.N) + blas64.Copy(blas64.Vector{N: aU.mat.N, Inc: amat.Inc, Data: amat.Data}, + blas64.Vector{N: aU.mat.N, Inc: 1, Data: mat.Data}) default: mat.Data = make([]float64, r*c) w := *m @@ -437,9 +451,8 @@ func (m *Dense) Copy(a Matrix) (r, c int) { 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]}) + blas64.Copy(blas64.Vector{N: c, Inc: amat.Stride, Data: amat.Data[i : i+(c-1)*amat.Stride+1]}, + blas64.Vector{N: c, Inc: 1, Data: m.mat.Data[i*m.mat.Stride : i*m.mat.Stride+c]}) } } else { switch o := offset(m.mat.Data, amat.Data); { @@ -474,13 +487,11 @@ func (m *Dense) Copy(a Matrix) (r, c int) { } 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}) + blas64.Copy(blas64.Vector{N: n, Inc: -amat.Inc, Data: amat.Data}, + blas64.Vector{N: n, 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}) + blas64.Copy(blas64.Vector{N: n, Inc: amat.Inc, Data: amat.Data}, + blas64.Vector{N: n, Inc: stride, Data: m.mat.Data}) default: // Nothing to do. } @@ -531,3 +542,17 @@ func (m *Dense) Augment(a, b Matrix) { w := m.Slice(0, br, ac, ac+bc).(*Dense) w.Copy(b) } + +// Trace returns the trace of the matrix. The matrix must be square or Trace +// will panic. +func (m *Dense) Trace() float64 { + if m.mat.Rows != m.mat.Cols { + panic(ErrSquare) + } + // TODO(btracey): could use internal asm sum routine. + var v float64 + for i := 0; i < m.mat.Rows; i++ { + v += m.mat.Data[i*m.mat.Stride+i] + } + return v +} diff --git a/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go b/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go index e909a6a197b..dd4526f634b 100644 --- a/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go +++ b/vendor/gonum.org/v1/gonum/mat/dense_arithmetic.go @@ -504,12 +504,13 @@ func (m *Dense) Exp(a Matrix) { a1.Copy(a) v := getWorkspace(r, r, true) vraw := v.RawMatrix() - vvec := blas64.Vector{Inc: 1, Data: vraw.Data} + n := r * r + vvec := blas64.Vector{N: n, Inc: 1, Data: vraw.Data} defer putWorkspace(v) u := getWorkspace(r, r, true) uraw := u.RawMatrix() - uvec := blas64.Vector{Inc: 1, Data: uraw.Data} + uvec := blas64.Vector{N: n, Inc: 1, Data: uraw.Data} defer putWorkspace(u) a2 := getWorkspace(r, r, false) @@ -525,7 +526,7 @@ func (m *Dense) Exp(a Matrix) { // this is not as horrible as it looks. p := getWorkspace(r, r, true) praw := p.RawMatrix() - pvec := blas64.Vector{Inc: 1, Data: praw.Data} + pvec := blas64.Vector{N: n, Inc: 1, Data: praw.Data} defer putWorkspace(p) for k := 0; k < r; k++ { @@ -537,8 +538,8 @@ func (m *Dense) Exp(a Matrix) { a2.Mul(a1, a1) for j := 0; j <= i; j++ { p.Mul(p, a2) - blas64.Axpy(r*r, t.b[2*j+2], pvec, vvec) - blas64.Axpy(r*r, t.b[2*j+3], pvec, uvec) + blas64.Axpy(t.b[2*j+2], pvec, vvec) + blas64.Axpy(t.b[2*j+3], pvec, uvec) } u.Mul(a1, u) @@ -573,43 +574,43 @@ func (m *Dense) Exp(a Matrix) { i.set(j, j, 1) } iraw := i.RawMatrix() - ivec := blas64.Vector{Inc: 1, Data: iraw.Data} + ivec := blas64.Vector{N: n, Inc: 1, Data: iraw.Data} defer putWorkspace(i) a2raw := a2.RawMatrix() - a2vec := blas64.Vector{Inc: 1, Data: a2raw.Data} + a2vec := blas64.Vector{N: n, Inc: 1, Data: a2raw.Data} a4 := getWorkspace(r, r, false) a4raw := a4.RawMatrix() - a4vec := blas64.Vector{Inc: 1, Data: a4raw.Data} + a4vec := blas64.Vector{N: n, Inc: 1, Data: a4raw.Data} defer putWorkspace(a4) a4.Mul(a2, a2) a6 := getWorkspace(r, r, false) a6raw := a6.RawMatrix() - a6vec := blas64.Vector{Inc: 1, Data: a6raw.Data} + a6vec := blas64.Vector{N: n, Inc: 1, Data: a6raw.Data} defer putWorkspace(a6) a6.Mul(a2, a4) // V = A_6(b_12*A_6 + b_10*A_4 + b_8*A_2) + b_6*A_6 + b_4*A_4 + b_2*A_2 +b_0*I - blas64.Axpy(r*r, b[12], a6vec, vvec) - blas64.Axpy(r*r, b[10], a4vec, vvec) - blas64.Axpy(r*r, b[8], a2vec, vvec) + blas64.Axpy(b[12], a6vec, vvec) + blas64.Axpy(b[10], a4vec, vvec) + blas64.Axpy(b[8], a2vec, vvec) v.Mul(v, a6) - blas64.Axpy(r*r, b[6], a6vec, vvec) - blas64.Axpy(r*r, b[4], a4vec, vvec) - blas64.Axpy(r*r, b[2], a2vec, vvec) - blas64.Axpy(r*r, b[0], ivec, vvec) + blas64.Axpy(b[6], a6vec, vvec) + blas64.Axpy(b[4], a4vec, vvec) + blas64.Axpy(b[2], a2vec, vvec) + blas64.Axpy(b[0], ivec, vvec) // U = A(A_6(b_13*A_6 + b_11*A_4 + b_9*A_2) + b_7*A_6 + b_5*A_4 + b_2*A_3 +b_1*I) - blas64.Axpy(r*r, b[13], a6vec, uvec) - blas64.Axpy(r*r, b[11], a4vec, uvec) - blas64.Axpy(r*r, b[9], a2vec, uvec) + blas64.Axpy(b[13], a6vec, uvec) + blas64.Axpy(b[11], a4vec, uvec) + blas64.Axpy(b[9], a2vec, uvec) u.Mul(u, a6) - blas64.Axpy(r*r, b[7], a6vec, uvec) - blas64.Axpy(r*r, b[5], a4vec, uvec) - blas64.Axpy(r*r, b[3], a2vec, uvec) - blas64.Axpy(r*r, b[1], ivec, uvec) + blas64.Axpy(b[7], a6vec, uvec) + blas64.Axpy(b[5], a4vec, uvec) + blas64.Axpy(b[3], a2vec, uvec) + blas64.Axpy(b[1], ivec, uvec) u.Mul(u, a1) // Use i as a workspace here and @@ -783,14 +784,14 @@ func (m *Dense) RankOne(a Matrix, alpha float64, x, y Vector) { xU, _ := untranspose(x) if rv, ok := xU.(RawVectorer); ok { xmat = rv.RawVector() - m.checkOverlap((&VecDense{mat: xmat, n: x.Len()}).asGeneral()) + m.checkOverlap((&VecDense{mat: xmat}).asGeneral()) } else { fast = false } yU, _ := untranspose(y) if rv, ok := yU.(RawVectorer); ok { ymat = rv.RawVector() - m.checkOverlap((&VecDense{mat: ymat, n: y.Len()}).asGeneral()) + m.checkOverlap((&VecDense{mat: ymat}).asGeneral()) } else { fast = false } @@ -856,7 +857,7 @@ func (m *Dense) Outer(alpha float64, x, y Vector) { xU, _ := untranspose(x) if rv, ok := xU.(RawVectorer); ok { xmat = rv.RawVector() - m.checkOverlap((&VecDense{mat: xmat, n: x.Len()}).asGeneral()) + m.checkOverlap((&VecDense{mat: xmat}).asGeneral()) } else { fast = false @@ -864,7 +865,7 @@ func (m *Dense) Outer(alpha float64, x, y Vector) { yU, _ := untranspose(y) if rv, ok := yU.(RawVectorer); ok { ymat = rv.RawVector() - m.checkOverlap((&VecDense{mat: ymat, n: y.Len()}).asGeneral()) + m.checkOverlap((&VecDense{mat: ymat}).asGeneral()) } else { fast = false } diff --git a/vendor/gonum.org/v1/gonum/mat/diagonal.go b/vendor/gonum.org/v1/gonum/mat/diagonal.go new file mode 100644 index 00000000000..e9f074a7fb3 --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/diagonal.go @@ -0,0 +1,311 @@ +// Copyright ©2018 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + diagDense *DiagDense + _ Matrix = diagDense + _ Diagonal = diagDense + _ MutableDiagonal = diagDense + _ Triangular = diagDense + _ TriBanded = diagDense + _ Symmetric = diagDense + _ SymBanded = diagDense + _ Banded = diagDense + _ RawBander = diagDense + _ RawSymBander = diagDense + + diag Diagonal + _ Matrix = diag + _ Diagonal = diag + _ Triangular = diag + _ TriBanded = diag + _ Symmetric = diag + _ SymBanded = diag + _ Banded = diag +) + +// Diagonal represents a diagonal matrix, that is a square matrix that only +// has non-zero terms on the diagonal. +type Diagonal interface { + Matrix + // Diag returns the number of rows/columns in the matrix. + Diag() int + + // Bandwidth and TBand are included in the Diagonal interface + // to allow the use of Diagonal types in banded functions. + // Bandwidth will always return (0, 0). + Bandwidth() (kl, ku int) + TBand() Banded + + // Triangle and TTri are included in the Diagonal interface + // to allow the use of Diagonal types in triangular functions. + Triangle() (int, TriKind) + TTri() Triangular + + // Symmetric and SymBand are included in the Diagonal interface + // to allow the use of Diagonal types in symmetric and banded symmetric + // functions respectively. + Symmetric() int + SymBand() (n, k int) + + // TriBand and TTriBand are included in the Diagonal interface + // to allow the use of Diagonal types in triangular banded functions. + TriBand() (n, k int, kind TriKind) + TTriBand() TriBanded +} + +// MutableDiagonal is a Diagonal matrix whose elements can be set. +type MutableDiagonal interface { + Diagonal + SetDiag(i int, v float64) +} + +// DiagDense represents a diagonal matrix in dense storage format. +type DiagDense struct { + mat blas64.Vector +} + +// NewDiagDense creates a new Diagonal matrix with n rows and n columns. +// The length of data must be n or data must be nil, otherwise NewDiagDense +// will panic. NewDiagDense will panic if n is zero. +func NewDiagDense(n int, data []float64) *DiagDense { + if n <= 0 { + if n == 0 { + panic(ErrZeroLength) + } + panic("mat: negative dimension") + } + if data == nil { + data = make([]float64, n) + } + if len(data) != n { + panic(ErrShape) + } + return &DiagDense{ + mat: blas64.Vector{N: n, Data: data, Inc: 1}, + } +} + +// Diag returns the dimension of the receiver. +func (d *DiagDense) Diag() int { + return d.mat.N +} + +// Dims returns the dimensions of the matrix. +func (d *DiagDense) Dims() (r, c int) { + return d.mat.N, d.mat.N +} + +// T returns the transpose of the matrix. +func (d *DiagDense) T() Matrix { + return d +} + +// TTri returns the transpose of the matrix. Note that Diagonal matrices are +// Upper by default. +func (d *DiagDense) TTri() Triangular { + return TransposeTri{d} +} + +// TBand performs an implicit transpose by returning the receiver inside a +// TransposeBand. +func (d *DiagDense) TBand() Banded { + return TransposeBand{d} +} + +// TTriBand performs an implicit transpose by returning the receiver inside a +// TransposeTriBand. Note that Diagonal matrices are Upper by default. +func (d *DiagDense) TTriBand() TriBanded { + return TransposeTriBand{d} +} + +// Bandwidth returns the upper and lower bandwidths of the matrix. +// These values are always zero for diagonal matrices. +func (d *DiagDense) Bandwidth() (kl, ku int) { + return 0, 0 +} + +// Symmetric implements the Symmetric interface. +func (d *DiagDense) Symmetric() int { + return d.mat.N +} + +// SymBand returns the number of rows/columns in the matrix, and the size of +// the bandwidth. +func (d *DiagDense) SymBand() (n, k int) { + return d.mat.N, 0 +} + +// Triangle implements the Triangular interface. +func (d *DiagDense) Triangle() (int, TriKind) { + return d.mat.N, Upper +} + +// TriBand returns the number of rows/columns in the matrix, the +// size of the bandwidth, and the orientation. Note that Diagonal matrices are +// Upper by default. +func (d *DiagDense) TriBand() (n, k int, kind TriKind) { + return d.mat.N, 0, Upper +} + +// Reset zeros the length 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 (d *DiagDense) Reset() { + // No change of Inc or n to 0 may be + // made unless both are set to 0. + d.mat.Inc = 0 + d.mat.N = 0 + d.mat.Data = d.mat.Data[:0] +} + +// Zero sets all of the matrix elements to zero. +func (d *DiagDense) Zero() { + for i := 0; i < d.mat.N; i++ { + d.mat.Data[d.mat.Inc*i] = 0 + } +} + +// DiagView returns the diagonal as a matrix backed by the original data. +func (d *DiagDense) DiagView() Diagonal { + return d +} + +// DiagFrom copies the diagonal of m into the receiver. The receiver must +// be min(r, c) long or zero. Otherwise DiagFrom will panic. +func (d *DiagDense) DiagFrom(m Matrix) { + n := min(m.Dims()) + d.reuseAs(n) + + var vec blas64.Vector + switch r := m.(type) { + case *DiagDense: + vec = r.mat + case RawBander: + mat := r.RawBand() + vec = blas64.Vector{ + N: n, + Inc: mat.Stride, + Data: mat.Data[mat.KL : (n-1)*mat.Stride+mat.KL+1], + } + case RawMatrixer: + mat := r.RawMatrix() + vec = blas64.Vector{ + N: n, + Inc: mat.Stride + 1, + Data: mat.Data[:(n-1)*mat.Stride+n], + } + case RawSymBander: + mat := r.RawSymBand() + vec = blas64.Vector{ + N: n, + Inc: mat.Stride, + Data: mat.Data[:(n-1)*mat.Stride+1], + } + case RawSymmetricer: + mat := r.RawSymmetric() + vec = blas64.Vector{ + N: n, + Inc: mat.Stride + 1, + Data: mat.Data[:(n-1)*mat.Stride+n], + } + case RawTriBander: + mat := r.RawTriBand() + data := mat.Data + if mat.Uplo == blas.Lower { + data = data[mat.K:] + } + vec = blas64.Vector{ + N: n, + Inc: mat.Stride, + Data: data[:(n-1)*mat.Stride+1], + } + case RawTriangular: + mat := r.RawTriangular() + if mat.Diag == blas.Unit { + for i := 0; i < n; i += d.mat.Inc { + d.mat.Data[i] = 1 + } + return + } + vec = blas64.Vector{ + N: n, + Inc: mat.Stride + 1, + Data: mat.Data[:(n-1)*mat.Stride+n], + } + case RawVectorer: + d.mat.Data[0] = r.RawVector().Data[0] + return + default: + for i := 0; i < n; i++ { + d.setDiag(i, m.At(i, i)) + } + return + } + blas64.Copy(vec, d.mat) +} + +// RawBand returns the underlying data used by the receiver represented +// as a blas64.Band. +// Changes to elements in the receiver following the call will be reflected +// in returned blas64.Band. +func (d *DiagDense) RawBand() blas64.Band { + return blas64.Band{ + Rows: d.mat.N, + Cols: d.mat.N, + KL: 0, + KU: 0, + Stride: d.mat.Inc, + Data: d.mat.Data, + } +} + +// RawSymBand returns the underlying data used by the receiver represented +// as a blas64.SymmetricBand. +// Changes to elements in the receiver following the call will be reflected +// in returned blas64.Band. +func (d *DiagDense) RawSymBand() blas64.SymmetricBand { + return blas64.SymmetricBand{ + N: d.mat.N, + K: 0, + Stride: d.mat.Inc, + Uplo: blas.Upper, + Data: d.mat.Data, + } +} + +// reuseAs resizes an empty diagonal to a r×r diagonal, +// or checks that a non-empty matrix is r×r. +func (d *DiagDense) reuseAs(r int) { + if r == 0 { + panic(ErrZeroLength) + } + if d.IsZero() { + d.mat = blas64.Vector{ + Inc: 1, + Data: use(d.mat.Data, r), + } + d.mat.N = r + return + } + if r != d.mat.N { + panic(ErrShape) + } +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized vectors can be the +// receiver for size-restricted operations. DiagDenses can be zeroed using Reset. +func (d *DiagDense) IsZero() bool { + // It must be the case that d.Dims() returns + // zeros in this case. See comment in Reset(). + return d.mat.Inc == 0 +} diff --git a/vendor/gonum.org/v1/gonum/mat/eigen.go b/vendor/gonum.org/v1/gonum/mat/eigen.go index 6204a70fcfb..ee971e4ae48 100644 --- a/vendor/gonum.org/v1/gonum/mat/eigen.go +++ b/vendor/gonum.org/v1/gonum/mat/eigen.go @@ -34,13 +34,17 @@ type EigenSym struct { // 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) { + // kill previous decomposition + e.vectorsComputed = false + e.values = e.values[:] + n := a.Symmetric() sd := NewSymDense(n, nil) sd.CopySym(a) - jobz := lapack.EVJob(lapack.None) + jobz := lapack.EVNone if vectors { - jobz = lapack.ComputeEV + jobz = lapack.EVCompute } w := make([]float64, n) work := []float64{0} @@ -87,38 +91,58 @@ func (e *EigenSym) Values(dst []float64) []float64 { 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. +// VectorsTo returns the eigenvectors of the decomposition. VectorsTo +// will panic if the eigenvectors were not computed during the factorization, +// or if the factorization was not successful. // -// EigenvectorsSym panics if the factorization was not successful or if the -// decomposition did not compute the eigenvectors. -func (m *Dense) EigenvectorsSym(e *EigenSym) { +// If dst is not nil, the eigenvectors are stored in-place into dst, and dst +// must have size n×n and panics otherwise. If dst is nil, a new matrix +// is allocated and returned. +func (e *EigenSym) VectorsTo(dst *Dense) *Dense { if !e.succFact() { panic(badFact) } if !e.vectorsComputed { panic(badNoVect) } - m.reuseAs(len(e.values), len(e.values)) - m.Copy(e.vectors) + r, c := e.vectors.Dims() + if dst == nil { + dst = NewDense(r, c, nil) + } else { + dst.reuseAs(r, c) + } + dst.Copy(e.vectors) + return dst } +// EigenKind specifies the computation of eigenvectors during factorization. +type EigenKind int + +const ( + // EigenNone specifies to not compute any eigenvectors. + EigenNone EigenKind = 0 + // EigenLeft specifies to compute the left eigenvectors. + EigenLeft EigenKind = 1 << iota + // EigenRight specifies to compute the right eigenvectors. + EigenRight + // EigenBoth is a convenience value for computing both eigenvectors. + EigenBoth EigenKind = EigenLeft | EigenRight +) + // 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 + kind EigenKind values []complex128 - rVectors *Dense - lVectors *Dense + rVectors *CDense + lVectors *CDense } // succFact returns whether the receiver contains a successful factorization. func (e *Eigen) succFact() bool { - return len(e.values) != 0 + return e.n != 0 } // Factorize computes the eigenvalues of the square matrix a, and optionally @@ -127,7 +151,7 @@ func (e *Eigen) succFact() bool { // 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. +// eigenvalue. // // Similarly, a left eigenvalue/eigenvector combination is defined by // x_l * A = λ * x_l @@ -135,16 +159,17 @@ func (e *Eigen) succFact() bool { // // 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. +// In all cases, Factorize computes the eigenvalues of the matrix. kind +// specifies which of the eigenvectors, if any, to compute. See the EigenKind +// documentation for more information. // 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 VecDenses as a *CMat when - // #308 is resolved. - +func (e *Eigen) Factorize(a Matrix, kind EigenKind) (ok bool) { + // kill previous factorization. + e.n = 0 + e.kind = 0 // Copy a because it is modified during the Lapack call. r, c := a.Dims() if r != c { @@ -153,16 +178,19 @@ func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) { var sd Dense sd.Clone(a) + left := kind&EigenLeft != 0 + right := kind&EigenRight != 0 + var vl, vr Dense - var jobvl lapack.LeftEVJob = lapack.None - var jobvr lapack.RightEVJob = lapack.None + jobvl := lapack.LeftEVNone + jobvr := lapack.RightEVNone if left { vl = *NewDense(r, r, nil) - jobvl = lapack.ComputeLeftEV + jobvl = lapack.LeftEVCompute } if right { vr = *NewDense(c, c, nil) - jobvr = lapack.ComputeRightEV + jobvr = lapack.RightEVCompute } wr := getFloats(c, false) @@ -181,18 +209,43 @@ func (e *Eigen) Factorize(a Matrix, left, right bool) (ok bool) { return false } e.n = r - e.right = right - e.left = left - e.lVectors = &vl - e.rVectors = &vr + e.kind = kind + + // Construct complex eigenvalues from float64 data. values := make([]complex128, r) for i, v := range wr { values[i] = complex(v, wi[i]) } e.values = values + + // Construct complex eigenvectors from float64 data. + var cvl, cvr CDense + if left { + cvl = *NewCDense(r, r, nil) + e.complexEigenTo(&cvl, &vl) + e.lVectors = &cvl + } else { + e.lVectors = nil + } + if right { + cvr = *NewCDense(c, c, nil) + e.complexEigenTo(&cvr, &vr) + e.rVectors = &cvr + } else { + e.rVectors = nil + } return true } +// Kind returns the EigenKind of the decomposition. If no decomposition has been +// computed, Kind returns -1. +func (e *Eigen) Kind() EigenKind { + if !e.succFact() { + return -1 + } + return e.kind +} + // 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 @@ -214,48 +267,84 @@ func (e *Eigen) Values(dst []complex128) []complex128 { return dst } -// Vectors returns the right eigenvectors of the decomposition. Vectors +// complexEigenTo extracts the complex eigenvectors from the real matrix d +// and stores them into the complex matrix dst. +// +// The columns of the returned n×n dense matrix contain the eigenvectors of the +// decomposition in the same order as the eigenvalues. +// If the j-th eigenvalue is real, then +// dst[:,j] = d[:,j], +// and if it is not real, then the elements of the j-th and (j+1)-th columns of d +// form complex conjugate pairs and the eigenvectors are recovered as +// dst[:,j] = d[:,j] + i*d[:,j+1], +// dst[:,j+1] = d[:,j] - i*d[:,j+1], +// where i is the imaginary unit. +func (e *Eigen) complexEigenTo(dst *CDense, d *Dense) { + r, c := d.Dims() + cr, cc := dst.Dims() + if r != cr { + panic("size mismatch") + } + if c != cc { + panic("size mismatch") + } + for j := 0; j < c; j++ { + if imag(e.values[j]) == 0 { + for i := 0; i < r; i++ { + dst.set(i, j, complex(d.at(i, j), 0)) + } + continue + } + for i := 0; i < r; i++ { + real := d.at(i, j) + imag := d.at(i, j+1) + dst.set(i, j, complex(real, imag)) + dst.set(i, j+1, complex(real, -imag)) + } + j++ + } +} + +// VectorsTo returns the right eigenvectors of the decomposition. VectorsTo // 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 { +// The computed eigenvectors are normalized to have Euclidean norm equal to 1 +// and largest component real. +func (e *Eigen) VectorsTo(dst *CDense) *CDense { if !e.succFact() { panic(badFact) } - if !e.right { + if e.kind&EigenRight == 0 { panic(badNoVect) } - return DenseCopyOf(e.rVectors) + if dst == nil { + dst = NewCDense(e.n, e.n, nil) + } else { + dst.reuseAs(e.n, e.n) + } + dst.Copy(e.rVectors) + return dst } -// LeftVectors returns the left eigenvectors of the decomposition. LeftVectors -// will panic if the left eigenvectors were not computed during the factorization. +// LeftVectorsTo returns the left eigenvectors of the decomposition. LeftVectorsTo +// 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 { +// The computed eigenvectors are normalized to have Euclidean norm equal to 1 +// and largest component real. +func (e *Eigen) LeftVectorsTo(dst *CDense) *CDense { if !e.succFact() { panic(badFact) } - if !e.left { + if e.kind&EigenLeft == 0 { panic(badNoVect) } - return DenseCopyOf(e.lVectors) + if dst == nil { + dst = NewCDense(e.n, e.n, nil) + } else { + dst.reuseAs(e.n, e.n) + } + dst.Copy(e.lVectors) + return dst } diff --git a/vendor/gonum.org/v1/gonum/mat/errors.go b/vendor/gonum.org/v1/gonum/mat/errors.go index e47ea71bbd9..0430d126f2a 100644 --- a/vendor/gonum.org/v1/gonum/mat/errors.go +++ b/vendor/gonum.org/v1/gonum/mat/errors.go @@ -130,6 +130,7 @@ var ( ErrTriangle = Error{"matrix: triangular storage mismatch"} ErrTriangleSet = Error{"matrix: triangular set out of bounds"} ErrBandSet = Error{"matrix: band set out of bounds"} + ErrDiagSet = Error{"matrix: diagonal 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"} diff --git a/vendor/gonum.org/v1/gonum/mat/format.go b/vendor/gonum.org/v1/gonum/mat/format.go index ce72eb19aa9..9b60cb31868 100644 --- a/vendor/gonum.org/v1/gonum/mat/format.go +++ b/vendor/gonum.org/v1/gonum/mat/format.go @@ -66,7 +66,7 @@ func (f formatter) Format(fs fmt.State, c rune) { } // 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 +// specifies the numerical representation 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; diff --git a/vendor/gonum.org/v1/gonum/mat/gsvd.go b/vendor/gonum.org/v1/gonum/mat/gsvd.go index f2b82cb5395..2de511a9feb 100644 --- a/vendor/gonum.org/v1/gonum/mat/gsvd.go +++ b/vendor/gonum.org/v1/gonum/mat/gsvd.go @@ -11,6 +11,29 @@ import ( "gonum.org/v1/gonum/lapack/lapack64" ) +// GSVDKind specifies the treatment of singular vectors during a GSVD +// factorization. +type GSVDKind int + +const ( + // GSVDNone specifies that no singular vectors should be computed during + // the decomposition. + GSVDNone GSVDKind = 0 + + // 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 + + // GSVDAll is a convenience value for computing all of the singular vectors. + GSVDAll = GSVDU | GSVDV | GSVDQ +) + // GSVD is a type for creating and using the Generalized Singular Value Decomposition // (GSVD) of a matrix. // @@ -28,12 +51,17 @@ type GSVD struct { iwork []int } +// succFact returns whether the receiver contains a successful factorization. +func (gsvd *GSVD) succFact() bool { + return gsvd.r != 0 +} + // 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 +// The full singular value decomposition (kind == GSVDAll) deconstructs A and B as // A = U * Σ₁ * [ 0 R ] * Q^T // // B = V * Σ₂ * [ 0 R ] * Q^T @@ -49,6 +77,10 @@ type GSVD struct { // 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 GSVDKind) (ok bool) { + // kill the previous decomposition + gsvd.r = 0 + gsvd.kind = 0 + r, c := a.Dims() gsvd.r, gsvd.c = r, c p, c := b.Dims() @@ -64,7 +96,7 @@ func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) { jobU = lapack.GSVDNone jobV = lapack.GSVDNone jobQ = lapack.GSVDNone - case (GSVDU|GSVDV|GSVDQ)&kind != 0: + case GSVDAll&kind != 0: if GSVDU&kind != 0 { jobU = lapack.GSVDU gsvd.u = blas64.General{ @@ -115,9 +147,12 @@ func (gsvd *GSVD) Factorize(a, b Matrix, kind GSVDKind) (ok bool) { return ok } -// Kind returns the matrix.GSVDKind of the decomposition. If no decomposition has been -// computed, Kind returns 0. +// Kind returns the GSVDKind of the decomposition. If no decomposition has been +// computed, Kind returns -1. func (gsvd *GSVD) Kind() GSVDKind { + if !gsvd.succFact() { + return -1 + } return gsvd.kind } @@ -134,8 +169,8 @@ func (gsvd *GSVD) Rank() (k, l int) { // // 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") + if !gsvd.succFact() { + panic(badFact) } r := gsvd.r c := gsvd.c @@ -159,8 +194,8 @@ func (gsvd *GSVD) GeneralizedValues(v []float64) []float64 { // // 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") + if !gsvd.succFact() { + panic(badFact) } r := gsvd.r c := gsvd.c @@ -184,8 +219,8 @@ func (gsvd *GSVD) ValuesA(s []float64) []float64 { // // 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") + if !gsvd.succFact() { + panic(badFact) } r := gsvd.r c := gsvd.c @@ -207,8 +242,8 @@ func (gsvd *GSVD) ValuesB(s []float64) []float64 { // // ZeroRTo will panic if the receiver does not contain a successful factorization. func (gsvd *GSVD) ZeroRTo(dst *Dense) *Dense { - if gsvd.kind == 0 { - panic("gsvd: no decomposition computed") + if !gsvd.succFact() { + panic(badFact) } r := gsvd.r c := gsvd.c @@ -245,8 +280,8 @@ func (gsvd *GSVD) ZeroRTo(dst *Dense) *Dense { // // SigmaATo will panic if the receiver does not contain a successful factorization. func (gsvd *GSVD) SigmaATo(dst *Dense) *Dense { - if gsvd.kind == 0 { - panic("gsvd: no decomposition computed") + if !gsvd.succFact() { + panic(badFact) } r := gsvd.r k := gsvd.k @@ -271,8 +306,8 @@ func (gsvd *GSVD) SigmaATo(dst *Dense) *Dense { // // SigmaBTo will panic if the receiver does not contain a successful factorization. func (gsvd *GSVD) SigmaBTo(dst *Dense) *Dense { - if gsvd.kind == 0 { - panic("gsvd: no decomposition computed") + if !gsvd.succFact() { + panic(badFact) } r := gsvd.r p := gsvd.p @@ -298,6 +333,9 @@ func (gsvd *GSVD) SigmaBTo(dst *Dense) *Dense { // // UTo will panic if the receiver does not contain a successful factorization. func (gsvd *GSVD) UTo(dst *Dense) *Dense { + if !gsvd.succFact() { + panic(badFact) + } if gsvd.kind&GSVDU == 0 { panic("mat: improper GSVD kind") } @@ -324,6 +362,9 @@ func (gsvd *GSVD) UTo(dst *Dense) *Dense { // // VTo will panic if the receiver does not contain a successful factorization. func (gsvd *GSVD) VTo(dst *Dense) *Dense { + if !gsvd.succFact() { + panic(badFact) + } if gsvd.kind&GSVDV == 0 { panic("mat: improper GSVD kind") } @@ -350,6 +391,9 @@ func (gsvd *GSVD) VTo(dst *Dense) *Dense { // // QTo will panic if the receiver does not contain a successful factorization. func (gsvd *GSVD) QTo(dst *Dense) *Dense { + if !gsvd.succFact() { + panic(badFact) + } if gsvd.kind&GSVDQ == 0 { panic("mat: improper GSVD kind") } diff --git a/vendor/gonum.org/v1/gonum/mat/hogsvd.go b/vendor/gonum.org/v1/gonum/mat/hogsvd.go index 4b0a8ba6792..bd843e6b36f 100644 --- a/vendor/gonum.org/v1/gonum/mat/hogsvd.go +++ b/vendor/gonum.org/v1/gonum/mat/hogsvd.go @@ -24,6 +24,11 @@ type HOGSVD struct { err error } +// succFact returns whether the receiver contains a successful factorization. +func (gsvd *HOGSVD) succFact() bool { + return gsvd.n != 0 +} + // 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. @@ -80,13 +85,13 @@ func (gsvd *HOGSVD) Factorize(m ...Matrix) (ok bool) { defer putWorkspace(sij) for i, ai := range a { for _, aj := range a[i+1:] { - gsvd.err = ai.SolveChol(sij, &aj) + gsvd.err = ai.SolveCholTo(sij, &aj) if gsvd.err != nil { return false } s.Add(s, sij) - gsvd.err = aj.SolveChol(sij, &ai) + gsvd.err = aj.SolveCholTo(sij, &ai) if gsvd.err != nil { return false } @@ -96,16 +101,27 @@ func (gsvd *HOGSVD) Factorize(m ...Matrix) (ok bool) { s.Scale(1/float64(len(m)*(len(m)-1)), s) var eig Eigen - ok = eig.Factorize(s.T(), false, true) + ok = eig.Factorize(s.T(), EigenRight) if !ok { gsvd.err = errors.New("hogsvd: eigen decomposition failed") return false } - v := eig.Vectors() + vc := eig.VectorsTo(nil) + // vc is guaranteed to have real eigenvalues. + rc, cc := vc.Dims() + v := NewDense(rc, cc, nil) + for i := 0; i < rc; i++ { + for j := 0; j < cc; j++ { + a := vc.At(i, j) + v.set(i, j, real(a)) + } + } + // Rescale the columns of v by their Frobenius norms. + // Work done in cv is reflected in v. var cv VecDense for j := 0; j < c; j++ { cv.ColViewOf(v, j) - cv.ScaleVec(1/blas64.Nrm2(c, cv.mat), &cv) + cv.ScaleVec(1/blas64.Nrm2(cv.mat), &cv) } b := make([]Dense, len(m)) @@ -146,8 +162,8 @@ func (gsvd *HOGSVD) Len() int { // // UTo will panic if the receiver does not contain a successful factorization. func (gsvd *HOGSVD) UTo(dst *Dense, n int) *Dense { - if gsvd.n == 0 { - panic("hogsvd: unsuccessful factorization") + if !gsvd.succFact() { + panic(badFact) } if n < 0 || gsvd.n <= n { panic("hogsvd: invalid index") @@ -176,14 +192,14 @@ func (gsvd *HOGSVD) UTo(dst *Dense, n int) *Dense { // // 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 !gsvd.succFact() { + panic(badFact) } if n < 0 || gsvd.n <= n { panic("hogsvd: invalid index") } - r, c := gsvd.b[n].Dims() + _, c := gsvd.b[n].Dims() if s == nil { s = make([]float64, c) } else if len(s) != c { @@ -192,7 +208,7 @@ func (gsvd *HOGSVD) Values(s []float64, n int) []float64 { var v VecDense for j := 0; j < c; j++ { v.ColViewOf(&gsvd.b[n], j) - s[j] = blas64.Nrm2(r, v.mat) + s[j] = blas64.Nrm2(v.mat) } return s } @@ -203,8 +219,8 @@ func (gsvd *HOGSVD) Values(s []float64, n int) []float64 { // // VTo will panic if the receiver does not contain a successful factorization. func (gsvd *HOGSVD) VTo(dst *Dense) *Dense { - if gsvd.n == 0 { - panic("hogsvd: unsuccessful factorization") + if !gsvd.succFact() { + panic(badFact) } if dst == nil { r, c := gsvd.v.Dims() diff --git a/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go b/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go index 3dd5cfc3dc9..59815a6768c 100644 --- a/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go +++ b/vendor/gonum.org/v1/gonum/mat/index_bound_checks.go @@ -38,6 +38,36 @@ 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, column j. +func (m *CDense) At(i, j int) complex128 { + return m.at(i, j) +} + +func (m *CDense) at(i, j int) complex128 { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(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 *CDense) Set(i, j int, v complex128) { + m.set(i, j, v) +} + +func (m *CDense) set(i, j int, v complex128) { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(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 *VecDense) At(i, j int) float64 { @@ -54,7 +84,7 @@ func (v *VecDense) AtVec(i int) float64 { } func (v *VecDense) at(i int) float64 { - if uint(i) >= uint(v.n) { + if uint(i) >= uint(v.mat.N) { panic(ErrRowAccess) } return v.mat.Data[i*v.mat.Inc] @@ -67,7 +97,7 @@ func (v *VecDense) SetVec(i int, val float64) { } func (v *VecDense) setVec(i int, val float64) { - if uint(i) >= uint(v.n) { + if uint(i) >= uint(v.mat.N) { panic(ErrVectorAccess) } v.mat.Data[i*v.mat.Inc] = val @@ -231,3 +261,88 @@ func (s *SymBandDense) set(i, j int, v float64) { } s.mat.Data[i*s.mat.Stride+pj] = v } + +func (t *TriBandDense) At(i, j int) float64 { + return t.at(i, j) +} + +func (t *TriBandDense) at(i, j int) float64 { + // TODO(btracey): Support Diag field, see #692. + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + return 0 + } + kl, ku := t.mat.K, 0 + if isUpper { + kl, ku = 0, t.mat.K + } + pj := j + kl - i + if pj < 0 || kl+ku+1 <= pj { + return 0 + } + return t.mat.Data[i*t.mat.Stride+pj] +} + +func (t *TriBandDense) SetTriBand(i, j int, v float64) { + t.setTriBand(i, j, v) +} + +func (t *TriBandDense) setTriBand(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + panic(ErrTriangleSet) + } + kl, ku := t.mat.K, 0 + if isUpper { + kl, ku = 0, t.mat.K + } + pj := j + kl - i + if pj < 0 || kl+ku+1 <= pj { + panic(ErrBandSet) + } + // TODO(btracey): Support Diag field, see #692. + t.mat.Data[i*t.mat.Stride+pj] = v +} + +// At returns the element at row i, column j. +func (d *DiagDense) At(i, j int) float64 { + return d.at(i, j) +} + +func (d *DiagDense) at(i, j int) float64 { + if uint(i) >= uint(d.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(d.mat.N) { + panic(ErrColAccess) + } + if i != j { + return 0 + } + return d.mat.Data[i*d.mat.Inc] +} + +// SetDiag sets the element at row i, column i to the value v. +// It panics if the location is outside the appropriate region of the matrix. +func (d *DiagDense) SetDiag(i int, v float64) { + d.setDiag(i, v) +} + +func (d *DiagDense) setDiag(i int, v float64) { + if uint(i) >= uint(d.mat.N) { + panic(ErrRowAccess) + } + d.mat.Data[i*d.mat.Inc] = v +} diff --git a/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go b/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go index 9a49a7f5bd6..051f8437afc 100644 --- a/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go +++ b/vendor/gonum.org/v1/gonum/mat/index_no_bound_checks.go @@ -38,10 +38,40 @@ 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, column j. +func (m *CDense) At(i, j int) complex128 { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(ErrColAccess) + } + return m.at(i, j) +} + +func (m *CDense) at(i, j int) complex128 { + return m.mat.Data[i*m.mat.Stride+j] +} + +// Set sets the element at row i, column j to the value v. +func (m *CDense) Set(i, j int, v complex128) { + if uint(i) >= uint(m.mat.Rows) { + panic(ErrRowAccess) + } + if uint(j) >= uint(m.mat.Cols) { + panic(ErrColAccess) + } + m.set(i, j, v) +} + +func (m *CDense) set(i, j int, v complex128) { + 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 *VecDense) At(i, j int) float64 { - if uint(i) >= uint(v.n) { + if uint(i) >= uint(v.mat.N) { panic(ErrRowAccess) } if j != 0 { @@ -53,7 +83,7 @@ func (v *VecDense) At(i, j int) float64 { // AtVec returns the element at row i. // It panics if i is out of bounds. func (v *VecDense) AtVec(i int) float64 { - if uint(i) >= uint(v.n) { + if uint(i) >= uint(v.mat.N) { panic(ErrRowAccess) } return v.at(i) @@ -66,7 +96,7 @@ func (v *VecDense) at(i int) float64 { // SetVec sets the element at row i to the value val. // It panics if i is out of bounds. func (v *VecDense) SetVec(i int, val float64) { - if uint(i) >= uint(v.n) { + if uint(i) >= uint(v.mat.N) { panic(ErrVectorAccess) } v.setVec(i, val) @@ -235,3 +265,95 @@ func (s *SymBandDense) set(i, j int, v float64) { } s.mat.Data[i*s.mat.Stride+pj] = v } + +func (t *TriBandDense) At(i, j int) float64 { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + return t.at(i, j) +} + +func (t *TriBandDense) at(i, j int) float64 { + // TODO(btracey): Support Diag field, see #692. + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + return 0 + } + kl := t.mat.K + ku := 0 + if isUpper { + ku = t.mat.K + kl = 0 + } + pj := j + kl - i + if pj < 0 || kl+ku+1 <= pj { + return 0 + } + return t.mat.Data[i*t.mat.Stride+pj] +} + +func (t *TriBandDense) SetTriBand(i, j int, v float64) { + if uint(i) >= uint(t.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(t.mat.N) { + panic(ErrColAccess) + } + isUpper := t.isUpper() + if (isUpper && i > j) || (!isUpper && i < j) { + panic(ErrTriangleSet) + } + kl, ku := t.mat.K, 0 + if isUpper { + kl, ku = 0, t.mat.K + } + pj := j + kl - i + if pj < 0 || kl+ku+1 <= pj { + panic(ErrBandSet) + } + // TODO(btracey): Support Diag field, see #692. + t.mat.Data[i*t.mat.Stride+pj] = v +} + +func (t *TriBandDense) setTriBand(i, j int, v float64) { + var kl int + if !t.isUpper() { + kl = t.mat.K + } + pj := j + kl - i + t.mat.Data[i*t.mat.Stride+pj] = v +} + +// At returns the element at row i, column j. +func (d *DiagDense) At(i, j int) float64 { + if uint(i) >= uint(d.mat.N) { + panic(ErrRowAccess) + } + if uint(j) >= uint(d.mat.N) { + panic(ErrColAccess) + } + return d.at(i, j) +} + +func (d *DiagDense) at(i, j int) float64 { + if i != j { + return 0 + } + return d.mat.Data[i*d.mat.Inc] +} + +// SetDiag sets the element at row i, column i to the value v. +// It panics if the location is outside the appropriate region of the matrix. +func (d *DiagDense) SetDiag(i int, v float64) { + if uint(i) >= uint(d.mat.N) { + panic(ErrRowAccess) + } + d.setDiag(i, v) +} + +func (d *DiagDense) setDiag(i int, v float64) { + d.mat.Data[i*d.mat.Inc] = v +} diff --git a/vendor/gonum.org/v1/gonum/mat/io.go b/vendor/gonum.org/v1/gonum/mat/io.go index 1111e4a4a5e..7f7ef0703ed 100644 --- a/vendor/gonum.org/v1/gonum/mat/io.go +++ b/vendor/gonum.org/v1/gonum/mat/io.go @@ -259,7 +259,7 @@ func (m *Dense) UnmarshalBinaryFrom(r io.Reader) (int, error) { // 32 - 39 0 (int64) // 40 - .. vector's data elements (float64) func (v VecDense) MarshalBinary() ([]byte, error) { - bufLen := int64(headerSize) + int64(v.n)*int64(sizeFloat64) + bufLen := int64(headerSize) + int64(v.mat.N)*int64(sizeFloat64) if bufLen <= 0 { // bufLen is too big and has wrapped around. return nil, errTooBig @@ -267,7 +267,7 @@ func (v VecDense) MarshalBinary() ([]byte, error) { header := storage{ Form: 'G', Packing: 'F', Uplo: 'A', - Rows: int64(v.n), Cols: 1, + Rows: int64(v.mat.N), Cols: 1, Version: version, } buf := make([]byte, bufLen) @@ -277,7 +277,7 @@ func (v VecDense) MarshalBinary() ([]byte, error) { } p := headerSize - for i := 0; i < v.n; i++ { + for i := 0; i < v.mat.N; i++ { binary.LittleEndian.PutUint64(buf[p:p+sizeFloat64], math.Float64bits(v.at(i))) p += sizeFloat64 } @@ -292,7 +292,7 @@ func (v VecDense) MarshalBinary() ([]byte, error) { func (v VecDense) MarshalBinaryTo(w io.Writer) (int, error) { header := storage{ Form: 'G', Packing: 'F', Uplo: 'A', - Rows: int64(v.n), Cols: 1, + Rows: int64(v.mat.N), Cols: 1, Version: version, } n, err := header.marshalBinaryTo(w) @@ -301,7 +301,7 @@ func (v VecDense) MarshalBinaryTo(w io.Writer) (int, error) { } var buf [8]byte - for i := 0; i < v.n; i++ { + for i := 0; i < v.mat.N; i++ { binary.LittleEndian.PutUint64(buf[:], math.Float64bits(v.at(i))) nn, err := w.Write(buf[:]) n += nn diff --git a/vendor/gonum.org/v1/gonum/mat/lq.go b/vendor/gonum.org/v1/gonum/mat/lq.go index 741a169229a..d788457d2b4 100644 --- a/vendor/gonum.org/v1/gonum/mat/lq.go +++ b/vendor/gonum.org/v1/gonum/mat/lq.go @@ -13,6 +13,8 @@ import ( "gonum.org/v1/gonum/lapack/lapack64" ) +const badLQ = "mat: invalid LQ factorization" + // LQ is a type for creating and using the LQ factorization of a matrix. type LQ struct { lq *Dense @@ -67,11 +69,16 @@ func (lq *LQ) factorize(a Matrix, norm lapack.MatrixNorm) { lq.updateCond(norm) } +// isValid returns whether the receiver contains a factorization. +func (lq *LQ) isValid() bool { + return lq.lq != nil && !lq.lq.IsZero() +} + // Cond returns the condition number for the factorized matrix. -// Cond will panic if the receiver does not contain a successful factorization. +// Cond will panic if the receiver does not contain a factorization. func (lq *LQ) Cond() float64 { - if lq.lq == nil || lq.lq.IsZero() { - panic("lq: no decomposition computed") + if !lq.isValid() { + panic(badLQ) } return lq.cond } @@ -81,7 +88,12 @@ func (lq *LQ) Cond() float64 { // LTo extracts the m×n lower trapezoidal matrix from a LQ decomposition. // If dst is nil, a new matrix is allocated. The resulting L matrix is returned. +// LTo will panic if the receiver does not contain a factorization. func (lq *LQ) LTo(dst *Dense) *Dense { + if !lq.isValid() { + panic(badLQ) + } + r, c := lq.lq.Dims() if dst == nil { dst = NewDense(r, c, nil) @@ -115,7 +127,12 @@ func (lq *LQ) LTo(dst *Dense) *Dense { // QTo extracts the n×n orthonormal matrix Q from an LQ decomposition. // If dst is nil, a new matrix is allocated. The resulting Q matrix is returned. +// QTo will panic if the receiver does not contain a factorization. func (lq *LQ) QTo(dst *Dense) *Dense { + if !lq.isValid() { + panic(badLQ) + } + _, c := lq.lq.Dims() if dst == nil { dst = NewDense(c, c, nil) @@ -140,7 +157,7 @@ func (lq *LQ) QTo(dst *Dense) *Dense { return dst } -// Solve finds a minimum-norm solution to a system of linear equations defined +// SolveTo 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. // See the documentation for Condition for more information. @@ -148,8 +165,13 @@ func (lq *LQ) QTo(dst *Dense) *Dense { // 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 x. -func (lq *LQ) Solve(x *Dense, trans bool, b Matrix) error { +// The solution matrix, X, is stored in place into dst. +// SolveTo will panic if the receiver does not contain a factorization. +func (lq *LQ) SolveTo(dst *Dense, trans bool, b Matrix) error { + if !lq.isValid() { + panic(badLQ) + } + r, c := lq.lq.Dims() br, bc := b.Dims() @@ -161,12 +183,12 @@ func (lq *LQ) Solve(x *Dense, trans bool, b Matrix) error { if c != br { panic(ErrShape) } - x.reuseAs(r, bc) + dst.reuseAs(r, bc) } else { if r != br { panic(ErrShape) } - x.reuseAs(c, bc) + dst.reuseAs(c, bc) } // Do not need to worry about overlap between x and b because w has its own // independent storage. @@ -199,7 +221,7 @@ func (lq *LQ) Solve(x *Dense, trans bool, b Matrix) error { putFloats(work) } // x was set above to be the correct size for the result. - x.Copy(w) + dst.Copy(w) putWorkspace(w) if lq.cond > ConditionTolerance { return Condition(lq.cond) @@ -207,9 +229,14 @@ func (lq *LQ) Solve(x *Dense, trans bool, b Matrix) error { return nil } -// SolveVec finds a minimum-norm solution to a system of linear equations. -// See LQ.Solve for the full documentation. -func (lq *LQ) SolveVec(x *VecDense, trans bool, b Vector) error { +// SolveVecTo finds a minimum-norm solution to a system of linear equations. +// See LQ.SolveTo for the full documentation. +// SolveToVec will panic if the receiver does not contain a factorization. +func (lq *LQ) SolveVecTo(dst *VecDense, trans bool, b Vector) error { + if !lq.isValid() { + panic(badLQ) + } + r, c := lq.lq.Dims() if _, bc := b.Dims(); bc != 1 { panic(ErrShape) @@ -220,16 +247,16 @@ func (lq *LQ) SolveVec(x *VecDense, trans bool, b Vector) error { bm := Matrix(b) if rv, ok := b.(RawVectorer); ok { bmat := rv.RawVector() - if x != b { - x.checkOverlap(bmat) + if dst != b { + dst.checkOverlap(bmat) } - b := VecDense{mat: bmat, n: b.Len()} + b := VecDense{mat: bmat} bm = b.asDense() } if trans { - x.reuseAs(r) + dst.reuseAs(r) } else { - x.reuseAs(c) + dst.reuseAs(c) } - return lq.Solve(x.asDense(), trans, bm) + return lq.SolveTo(dst.asDense(), trans, bm) } diff --git a/vendor/gonum.org/v1/gonum/mat/lu.go b/vendor/gonum.org/v1/gonum/mat/lu.go index 055ae6cb4d3..e0437169be6 100644 --- a/vendor/gonum.org/v1/gonum/mat/lu.go +++ b/vendor/gonum.org/v1/gonum/mat/lu.go @@ -14,7 +14,10 @@ import ( "gonum.org/v1/gonum/lapack/lapack64" ) -const badSliceLength = "mat: improper slice length" +const ( + badSliceLength = "mat: improper slice length" + badLU = "mat: invalid LU factorization" +) // LU is a type for creating and using the LU factorization of a matrix. type LU struct { @@ -83,11 +86,16 @@ func (lu *LU) factorize(a Matrix, norm lapack.MatrixNorm) { lu.updateCond(anorm, norm) } +// isValid returns whether the receiver contains a factorization. +func (lu *LU) isValid() bool { + return lu.lu != nil && !lu.lu.IsZero() +} + // Cond returns the condition number for the factorized matrix. -// Cond will panic if the receiver does not contain a successful factorization. +// Cond will panic if the receiver does not contain a factorization. func (lu *LU) Cond() float64 { - if lu.lu == nil || lu.lu.IsZero() { - panic("lu: no decomposition computed") + if !lu.isValid() { + panic(badLU) } return lu.cond } @@ -107,6 +115,7 @@ func (lu *LU) isZero() bool { // Det returns the determinant of the matrix that has been factorized. In many // expressions, using LogDet will be more numerically stable. +// Det will panic if the receiver does not contain a factorization. func (lu *LU) Det() float64 { det, sign := lu.LogDet() return math.Exp(det) * sign @@ -115,7 +124,12 @@ func (lu *LU) Det() float64 { // 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. +// LogDet will panic if the receiver does not contain a factorization. func (lu *LU) LogDet() (det float64, sign float64) { + if !lu.isValid() { + panic(badLU) + } + _, n := lu.lu.Dims() logDiag := getFloats(n, false) defer putFloats(logDiag) @@ -137,7 +151,12 @@ func (lu *LU) LogDet() (det float64, sign float64) { // 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. +// Pivot will panic if the receiver does not contain a factorization. func (lu *LU) Pivot(swaps []int) []int { + if !lu.isValid() { + panic(badLU) + } + _, n := lu.lu.Dims() if swaps == nil { swaps = make([]int, n) @@ -161,7 +180,12 @@ func (lu *LU) Pivot(swaps []int) []int { // 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. +// RankOne will panic if orig does not contain a factorization. func (lu *LU) RankOne(orig *LU, alpha float64, x, y Vector) { + if !orig.isValid() { + panic(badLU) + } + // 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 @@ -227,7 +251,12 @@ func (lu *LU) RankOne(orig *LU, alpha float64, x, y Vector) { // LTo extracts the lower triangular matrix from an LU factorization. // If dst is nil, a new matrix is allocated. The resulting L matrix is returned. +// LTo will panic if the receiver does not contain a factorization. func (lu *LU) LTo(dst *TriDense) *TriDense { + if !lu.isValid() { + panic(badLU) + } + _, n := lu.lu.Dims() if dst == nil { dst = NewTriDense(n, Lower, nil) @@ -249,7 +278,12 @@ func (lu *LU) LTo(dst *TriDense) *TriDense { // UTo extracts the upper triangular matrix from an LU factorization. // If dst is nil, a new matrix is allocated. The resulting U matrix is returned. +// UTo will panic if the receiver does not contain a factorization. func (lu *LU) UTo(dst *TriDense) *TriDense { + if !lu.isValid() { + panic(badLU) + } + _, n := lu.lu.Dims() if dst == nil { dst = NewTriDense(n, Upper, nil) @@ -281,16 +315,21 @@ func (m *Dense) Permutation(r int, swaps []int) { } } -// Solve solves a system of linear equations using the LU decomposition of a matrix. +// SolveTo 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 x. +// stored into dst. // // If A is singular or near-singular a Condition error is returned. See // the documentation for Condition for more information. -func (lu *LU) Solve(x *Dense, trans bool, b Matrix) error { +// SolveTo will panic if the receiver does not contain a factorization. +func (lu *LU) SolveTo(dst *Dense, trans bool, b Matrix) error { + if !lu.isValid() { + panic(badLU) + } + _, n := lu.lu.Dims() br, bc := b.Dims() if br != n { @@ -302,49 +341,54 @@ func (lu *LU) Solve(x *Dense, trans bool, b Matrix) error { return Condition(math.Inf(1)) } - x.reuseAs(n, bc) + dst.reuseAs(n, bc) bU, _ := untranspose(b) var restore func() - if x == bU { - x, restore = x.isolatedWorkspace(bU) + if dst == bU { + dst, restore = dst.isolatedWorkspace(bU) defer restore() } else if rm, ok := bU.(RawMatrixer); ok { - x.checkOverlap(rm.RawMatrix()) + dst.checkOverlap(rm.RawMatrix()) } - x.Copy(b) + dst.Copy(b) t := blas.NoTrans if trans { t = blas.Trans } - lapack64.Getrs(t, lu.lu.mat, x.mat, lu.pivot) + lapack64.Getrs(t, lu.lu.mat, dst.mat, lu.pivot) if lu.cond > ConditionTolerance { return Condition(lu.cond) } return nil } -// SolveVec solves a system of linear equations using the LU decomposition of a matrix. +// SolveVecTo 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 vector x is -// stored into x. +// stored into dst. // // If A is singular or near-singular a Condition error is returned. See // the documentation for Condition for more information. -func (lu *LU) SolveVec(x *VecDense, trans bool, b Vector) error { +// SolveVecTo will panic if the receiver does not contain a factorization. +func (lu *LU) SolveVecTo(dst *VecDense, trans bool, b Vector) error { + if !lu.isValid() { + panic(badLU) + } + _, n := lu.lu.Dims() if br, bc := b.Dims(); br != n || bc != 1 { panic(ErrShape) } switch rv := b.(type) { default: - x.reuseAs(n) - return lu.Solve(x.asDense(), trans, b) + dst.reuseAs(n) + return lu.SolveTo(dst.asDense(), trans, b) case RawVectorer: - if x != b { - x.checkOverlap(rv.RawVector()) + if dst != b { + dst.checkOverlap(rv.RawVector()) } // TODO(btracey): Should test the condition number instead of testing that // the determinant is exactly zero. @@ -352,18 +396,18 @@ func (lu *LU) SolveVec(x *VecDense, trans bool, b Vector) error { return Condition(math.Inf(1)) } - x.reuseAs(n) + dst.reuseAs(n) var restore func() - if x == b { - x, restore = x.isolatedWorkspace(b) + if dst == b { + dst, restore = dst.isolatedWorkspace(b) defer restore() } - x.CopyVec(b) + dst.CopyVec(b) vMat := blas64.General{ Rows: n, Cols: 1, - Stride: x.mat.Inc, - Data: x.mat.Data, + Stride: dst.mat.Inc, + Data: dst.mat.Data, } t := blas.NoTrans if trans { diff --git a/vendor/gonum.org/v1/gonum/mat/matrix.go b/vendor/gonum.org/v1/gonum/mat/matrix.go index 59f945831da..444d0445799 100644 --- a/vendor/gonum.org/v1/gonum/mat/matrix.go +++ b/vendor/gonum.org/v1/gonum/mat/matrix.go @@ -89,6 +89,13 @@ type UntransposeTrier interface { UntransposeTri() Triangular } +// UntransposeTriBander is a type that can undo an implicit triangular banded +// transpose. +type UntransposeTriBander interface { + // Untranspose returns the underlying Triangular stored for the implicit transpose. + UntransposeTriBand() TriBanded +} + // 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. @@ -200,6 +207,73 @@ type ColNonZeroDoer interface { DoColNonZero(j int, fn func(i, j int, v float64)) } +// 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 +} + +// untransposeExtract returns an untransposed matrix in a built-in matrix type. +// +// The untransposed matrix is returned unaltered if it is a built-in matrix type. +// Otherwise, if it implements a Raw method, an appropriate built-in type value +// is returned holding the raw matrix value of the input. If neither of these +// is possible, the untransposed matrix is returned. +func untransposeExtract(a Matrix) (Matrix, bool) { + ut, trans := untranspose(a) + switch m := ut.(type) { + case *DiagDense, *SymBandDense, *TriBandDense, *BandDense, *TriDense, *SymDense, *Dense: + return m, trans + // TODO(btracey): Add here if we ever have an equivalent of RawDiagDense. + case RawSymBander: + rsb := m.RawSymBand() + if rsb.Uplo != blas.Upper { + return ut, trans + } + var sb SymBandDense + sb.SetRawSymBand(rsb) + return &sb, trans + case RawTriBander: + rtb := m.RawTriBand() + if rtb.Diag == blas.Unit { + return ut, trans + } + var tb TriBandDense + tb.SetRawTriBand(rtb) + return &tb, trans + case RawBander: + var b BandDense + b.SetRawBand(m.RawBand()) + return &b, trans + case RawTriangular: + rt := m.RawTriangular() + if rt.Diag == blas.Unit { + return ut, trans + } + var t TriDense + t.SetRawTriangular(rt) + return &t, trans + case RawSymmetricer: + rs := m.RawSymmetric() + if rs.Uplo != blas.Upper { + return ut, trans + } + var s SymDense + s.SetRawSymmetric(rs) + return &s, trans + case RawMatrixer: + var d Dense + d.SetRawMatrix(m.RawMatrix()) + return &d, trans + default: + return ut, trans + } +} + // 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.) @@ -226,9 +300,8 @@ func Col(dst []float64, j int, a Matrix) []float64 { 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}, + blas64.Copy(blas64.Vector{N: r, Inc: m.Stride, Data: m.Data[j:]}, + blas64.Vector{N: r, Inc: 1, Data: dst}, ) return dst } @@ -257,9 +330,8 @@ func Row(dst []float64, i int, a Matrix) []float64 { 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}, + blas64.Copy(blas64.Vector{N: c, Inc: m.Stride, Data: m.Data[i:]}, + blas64.Vector{N: c, Inc: 1, Data: dst}, ) return dst } @@ -338,7 +410,7 @@ func Dot(a, b Vector) float64 { } if arv, ok := a.(RawVectorer); ok { if brv, ok := b.(RawVectorer); ok { - return blas64.Dot(la, arv.RawVector(), brv.RawVector()) + return blas64.Dot(arv.RawVector(), brv.RawVector()) } } var sum float64 @@ -401,7 +473,7 @@ func Equal(a, b Matrix) bool { if rb, ok := bU.(*VecDense); 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++ { + for i := 0; i < ra.mat.N; i++ { if ra.mat.Data[i*ra.mat.Inc] != rb.mat.Data[i*rb.mat.Inc] { return false } @@ -473,7 +545,7 @@ func EqualApprox(a, b Matrix, epsilon float64) bool { if rb, ok := bU.(*VecDense); 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++ { + for i := 0; i < ra.mat.N; i++ { if !floats.EqualWithinAbsOrRel(ra.mat.Data[i*ra.mat.Inc], rb.mat.Data[i*rb.mat.Inc], epsilon, epsilon) { return false } @@ -699,17 +771,17 @@ func Norm(a Matrix, norm float64) float64 { panic("unreachable") case 1: if aTrans { - imax := blas64.Iamax(rma.n, rv) + imax := blas64.Iamax(rv) return math.Abs(rma.At(imax, 0)) } - return blas64.Asum(rma.n, rv) + return blas64.Asum(rv) case 2: - return blas64.Nrm2(rma.n, rv) + return blas64.Nrm2(rv) case math.Inf(1): if aTrans { - return blas64.Asum(rma.n, rv) + return blas64.Asum(rv) } - imax := blas64.Iamax(rma.n, rv) + imax := blas64.Iamax(rv) return math.Abs(rma.At(imax, 0)) } } @@ -762,7 +834,7 @@ func normLapack(norm float64, aTrans bool) lapack.MatrixNorm { } return n case 2: - return lapack.NormFrob + return lapack.Frobenius case math.Inf(1): n := lapack.MaxRowSum if aTrans { @@ -798,44 +870,28 @@ func Sum(a Matrix) float64 { return sum } +// A Tracer can compute the trace of the matrix. Trace must panic if the +// matrix is not square. +type Tracer interface { + Trace() float64 +} + // Trace returns the trace of the matrix. Trace will panic if the // matrix is not square. func Trace(a Matrix) float64 { + m, _ := untransposeExtract(a) + if t, ok := m.(Tracer); ok { + return t.Trace() + } r, c := a.Dims() if r != c { panic(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 + var v float64 + for i := 0; i < r; i++ { + v += a.At(i, i) } + return v } func min(a, b int) int { diff --git a/vendor/gonum.org/v1/gonum/mat/pool.go b/vendor/gonum.org/v1/gonum/mat/pool.go index 065fd54226a..25ca29f18f2 100644 --- a/vendor/gonum.org/v1/gonum/mat/pool.go +++ b/vendor/gonum.org/v1/gonum/mat/pool.go @@ -186,7 +186,7 @@ func getWorkspaceVec(n int, clear bool) *VecDense { if clear { zero(v.mat.Data) } - v.n = n + v.mat.N = n return v } diff --git a/vendor/gonum.org/v1/gonum/mat/qr.go b/vendor/gonum.org/v1/gonum/mat/qr.go index c56845c771c..bf38ee4d6da 100644 --- a/vendor/gonum.org/v1/gonum/mat/qr.go +++ b/vendor/gonum.org/v1/gonum/mat/qr.go @@ -13,6 +13,8 @@ import ( "gonum.org/v1/gonum/lapack/lapack64" ) +const badQR = "mat: invalid QR factorization" + // QR is a type for creating and using the QR factorization of a matrix. type QR struct { qr *Dense @@ -68,11 +70,16 @@ func (qr *QR) factorize(a Matrix, norm lapack.MatrixNorm) { qr.updateCond(norm) } +// isValid returns whether the receiver contains a factorization. +func (qr *QR) isValid() bool { + return qr.qr != nil && !qr.qr.IsZero() +} + // Cond returns the condition number for the factorized matrix. -// Cond will panic if the receiver does not contain a successful factorization. +// Cond will panic if the receiver does not contain a factorization. func (qr *QR) Cond() float64 { - if qr.qr == nil || qr.qr.IsZero() { - panic("qr: no decomposition computed") + if !qr.isValid() { + panic(badQR) } return qr.cond } @@ -82,7 +89,12 @@ func (qr *QR) Cond() float64 { // RTo extracts the m×n upper trapezoidal matrix from a QR decomposition. // If dst is nil, a new matrix is allocated. The resulting dst matrix is returned. +// RTo will panic if the receiver does not contain a factorization. func (qr *QR) RTo(dst *Dense) *Dense { + if !qr.isValid() { + panic(badQR) + } + r, c := qr.qr.Dims() if dst == nil { dst = NewDense(r, c, nil) @@ -113,7 +125,12 @@ func (qr *QR) RTo(dst *Dense) *Dense { // QTo extracts the m×m orthonormal matrix Q from a QR decomposition. // If dst is nil, a new matrix is allocated. The resulting Q matrix is returned. +// QTo will panic if the receiver does not contain a factorization. func (qr *QR) QTo(dst *Dense) *Dense { + if !qr.isValid() { + panic(badQR) + } + r, _ := qr.qr.Dims() if dst == nil { dst = NewDense(r, r, nil) @@ -136,7 +153,7 @@ func (qr *QR) QTo(dst *Dense) *Dense { return dst } -// Solve finds a minimum-norm solution to a system of linear equations defined +// SolveTo 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. // See the documentation for Condition for more information. @@ -144,8 +161,13 @@ func (qr *QR) QTo(dst *Dense) *Dense { // 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 m. -func (qr *QR) Solve(x *Dense, trans bool, b Matrix) error { +// The solution matrix, X, is stored in place into dst. +// SolveTo will panic if the receiver does not contain a factorization. +func (qr *QR) SolveTo(dst *Dense, trans bool, b Matrix) error { + if !qr.isValid() { + panic(badQR) + } + r, c := qr.qr.Dims() br, bc := b.Dims() @@ -157,12 +179,12 @@ func (qr *QR) Solve(x *Dense, trans bool, b Matrix) error { if c != br { panic(ErrShape) } - x.reuseAs(r, bc) + dst.reuseAs(r, bc) } else { if r != br { panic(ErrShape) } - x.reuseAs(c, bc) + dst.reuseAs(c, bc) } // Do not need to worry about overlap between m and b because x has its own // independent storage. @@ -195,7 +217,7 @@ func (qr *QR) Solve(x *Dense, trans bool, b Matrix) error { } } // X was set above to be the correct size for the result. - x.Copy(w) + dst.Copy(w) putWorkspace(w) if qr.cond > ConditionTolerance { return Condition(qr.cond) @@ -203,10 +225,15 @@ func (qr *QR) Solve(x *Dense, trans bool, b Matrix) error { return nil } -// SolveVec finds a minimum-norm solution to a system of linear equations, +// SolveVecTo finds a minimum-norm solution to a system of linear equations, // Ax = b. -// See QR.Solve for the full documentation. -func (qr *QR) SolveVec(x *VecDense, trans bool, b Vector) error { +// See QR.SolveTo for the full documentation. +// SolveVecTo will panic if the receiver does not contain a factorization. +func (qr *QR) SolveVecTo(dst *VecDense, trans bool, b Vector) error { + if !qr.isValid() { + panic(badQR) + } + r, c := qr.qr.Dims() if _, bc := b.Dims(); bc != 1 { panic(ErrShape) @@ -217,17 +244,17 @@ func (qr *QR) SolveVec(x *VecDense, trans bool, b Vector) error { bm := Matrix(b) if rv, ok := b.(RawVectorer); ok { bmat := rv.RawVector() - if x != b { - x.checkOverlap(bmat) + if dst != b { + dst.checkOverlap(bmat) } - b := VecDense{mat: bmat, n: b.Len()} + b := VecDense{mat: bmat} bm = b.asDense() } if trans { - x.reuseAs(r) + dst.reuseAs(r) } else { - x.reuseAs(c) + dst.reuseAs(c) } - return qr.Solve(x.asDense(), trans, bm) + return qr.SolveTo(dst.asDense(), trans, bm) } diff --git a/vendor/gonum.org/v1/gonum/mat/solve.go b/vendor/gonum.org/v1/gonum/mat/solve.go index cbf0ed9d966..11813280f84 100644 --- a/vendor/gonum.org/v1/gonum/mat/solve.go +++ b/vendor/gonum.org/v1/gonum/mat/solve.go @@ -91,15 +91,15 @@ func (m *Dense) Solve(a, b Matrix) error { } var lu LU lu.Factorize(a) - return lu.Solve(m, false, b) + return lu.SolveTo(m, false, b) case ar > ac: var qr QR qr.Factorize(a) - return qr.Solve(m, false, b) + return qr.SolveTo(m, false, b) default: var lq LQ lq.Factorize(a) - return lq.Solve(m, false, b) + return lq.SolveTo(m, false, b) } } @@ -128,7 +128,7 @@ func (v *VecDense) SolveVec(a Matrix, b Vector) error { // and bm as overlapping but not identical. bm := m if v != b { - b := VecDense{mat: bmat, n: b.Len()} + b := VecDense{mat: bmat} bm = b.asDense() } return m.Solve(a, bm) diff --git a/vendor/gonum.org/v1/gonum/mat/svd.go b/vendor/gonum.org/v1/gonum/mat/svd.go index ef1f21cf6e0..2f55c4114b1 100644 --- a/vendor/gonum.org/v1/gonum/mat/svd.go +++ b/vendor/gonum.org/v1/gonum/mat/svd.go @@ -20,69 +20,106 @@ type SVD struct { 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 +// 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 = 0 + + // SVDThinU specifies the thin decomposition for U should be computed. + SVDThinU SVDKind = 1 << (iota - 1) + // SVDFullU specifies the full decomposition for U should be computed. + SVDFullU + // SVDThinV specifies the thin decomposition for V should be computed. + SVDThinV + // SVDFullV specifies the full decomposition for V should be computed. + SVDFullV + + // SVDThin is a convenience value for computing both thin vectors. + SVDThin SVDKind = SVDThinU | SVDThinV + // SVDThin is a convenience value for computing both full vectors. + SVDFull SVDKind = SVDFullU | SVDFullV +) + +// succFact returns whether the receiver contains a successful factorization. +func (svd *SVD) succFact() bool { + return len(svd.s) != 0 +} + +// 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 +// The full singular value decomposition (kind == SVDFull) is a factorization +// of an m×n matrix A of the form // 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. +// where Σ is an m×n diagonal matrix, U is an m×m orthogonal matrix, and V is an +// n×n orthogonal matrix. The diagonal elements of Σ are the singular values of A. +// The first min(m,n) columns of U and V are, respectively, the left and right +// singular vectors of A. // -// 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. +// Significant storage space can be saved by using the thin representation of +// the SVD (kind == SVDThin) instead of the full SVD, especially if +// m >> n or m << n. The thin SVD finds +// 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). // // 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 SVDKind) (ok bool) { + // kill previous factorization + svd.s = svd.s[:0] + svd.kind = kind + m, n := a.Dims() var jobU, jobVT lapack.SVDJob - switch kind { - default: - panic("svd: bad input kind") - case SVDNone: - jobU = lapack.SVDNone - jobVT = lapack.SVDNone - case 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. + + // 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. + switch { + case kind&SVDFullU != 0: + jobU = lapack.SVDAll 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 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. + case kind&SVDThinU != 0: + jobU = lapack.SVDStore svd.u = blas64.General{ Rows: m, Cols: min(m, n), Stride: min(m, n), Data: use(svd.u.Data, m*min(m, n)), } + default: + jobU = lapack.SVDNone + } + switch { + case kind&SVDFullV != 0: + svd.vt = blas64.General{ + Rows: n, + Cols: n, + Stride: n, + Data: use(svd.vt.Data, n*n), + } + jobVT = lapack.SVDAll + case kind&SVDThinV != 0: 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 + jobVT = lapack.SVDStore + default: + jobVT = lapack.SVDNone } // A is destroyed on call, so copy the matrix. @@ -101,31 +138,35 @@ func (svd *SVD) Factorize(a Matrix, kind SVDKind) (ok bool) { return ok } -// Kind returns the matrix.SVDKind of the decomposition. If no decomposition has been -// computed, Kind returns 0. +// Kind returns the SVDKind of the decomposition. If no decomposition has been +// computed, Kind returns -1. func (svd *SVD) Kind() SVDKind { + if !svd.succFact() { + return -1 + } 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") + if !svd.succFact() { + panic(badFact) } 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 returns the singular values of the factorized matrix in descending 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 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 !svd.succFact() { + panic(badFact) } if s == nil { s = make([]float64, len(svd.s)) @@ -137,13 +178,21 @@ func (svd *SVD) Values(s []float64) []float64 { return s } -// UTo extracts the matrix U from the singular value decomposition, storing -// the result in-place into dst. U is size m×m if svd.Kind() == SVDFull, -// of size m×min(m,n) if svd.Kind() == SVDThin, and UTo panics otherwise. +// UTo extracts the matrix U from the singular value decomposition. The first +// min(m,n) columns are the left singular vectors and correspond to the singular +// values as returned from SVD.Values. +// +// If dst is not nil, U is stored in-place into dst, and dst must have size +// m×m if the full U was computed, size m×min(m,n) if the thin U was computed, +// and UTo panics otherwise. If dst is nil, a new matrix of the appropriate size +// is allocated and returned. func (svd *SVD) UTo(dst *Dense) *Dense { + if !svd.succFact() { + panic(badFact) + } kind := svd.kind - if kind != SVDFull && kind != SVDThin { - panic("mat: improper SVD kind") + if kind&SVDThinU == 0 && kind&SVDFullU == 0 { + panic("svd: u not computed during factorization") } r := svd.u.Rows c := svd.u.Cols @@ -163,13 +212,21 @@ func (svd *SVD) UTo(dst *Dense) *Dense { return dst } -// VTo extracts the matrix V from the singular value decomposition, storing -// the result in-place into dst. V is size n×n if svd.Kind() == SVDFull, -// of size n×min(m,n) if svd.Kind() == SVDThin, and VTo panics otherwise. +// VTo extracts the matrix V from the singular value decomposition. The first +// min(m,n) columns are the right singular vectors and correspond to the singular +// values as returned from SVD.Values. +// +// If dst is not nil, V is stored in-place into dst, and dst must have size +// n×n if the full V was computed, size n×min(m,n) if the thin V was computed, +// and VTo panics otherwise. If dst is nil, a new matrix of the appropriate size +// is allocated and returned. func (svd *SVD) VTo(dst *Dense) *Dense { + if !svd.succFact() { + panic(badFact) + } kind := svd.kind - if kind != SVDFull && kind != SVDThin { - panic("mat: improper SVD kind") + if kind&SVDThinU == 0 && kind&SVDFullV == 0 { + panic("svd: v not computed during factorization") } r := svd.vt.Rows c := svd.vt.Cols diff --git a/vendor/gonum.org/v1/gonum/mat/symband.go b/vendor/gonum.org/v1/gonum/mat/symband.go index 967c5ff3f1a..add9a807d37 100644 --- a/vendor/gonum.org/v1/gonum/mat/symband.go +++ b/vendor/gonum.org/v1/gonum/mat/symband.go @@ -14,6 +14,7 @@ var ( _ Matrix = symBandDense _ Symmetric = symBandDense _ Banded = symBandDense + _ SymBanded = symBandDense _ RawSymBander = symBandDense _ MutableSymBanded = symBandDense @@ -27,11 +28,22 @@ type SymBandDense struct { mat blas64.SymmetricBand } +// SymBanded is a symmetric band matrix interface type. +type SymBanded interface { + Banded + + // Symmetric returns the number of rows/columns in the matrix. + Symmetric() int + + // SymBand returns the number of rows/columns in the matrix, and the size of + // the bandwidth. + SymBand() (n, k int) +} + // MutableSymBanded is a symmetric band matrix interface type that allows elements // to be altered. type MutableSymBanded interface { - Symmetric - Bandwidth() (kl, ku int) + SymBanded SetSymBand(i, j int, v float64) } @@ -46,7 +58,7 @@ type RawSymBander interface { // a new slice is allocated for the backing slice. If len(data) == n*(k+1), // data is used as the backing slice, and changes to the elements of the returned // SymBandDense will be reflected in data. If neither of these is true, NewSymBandDense -// will panic. k must be at least zero and less than n, otherwise NewBandDense will panic. +// will panic. k must be at least zero and less than n, otherwise NewSymBandDense will panic. // // The data must be arranged in row-major order constructed by removing the zeros // from the rows outside the band and aligning the diagonals. SymBandDense matrices @@ -64,10 +76,13 @@ type RawSymBander interface { // 10 11 12 // 13 14 * // 15 * * -// which is passed to NewBandDense as []float64{1, 2, 3, 4, ...} with k=2. +// which is passed to NewSymBandDense as []float64{1, 2, ..., 15, *, *, *} with k=2. // Only the values in the band portion of the matrix are used. func NewSymBandDense(n, k int, data []float64) *SymBandDense { - if n < 0 || k < 0 { + if n <= 0 || k < 0 { + if n == 0 { + panic(ErrZeroLength) + } panic("mat: negative dimension") } if k+1 > n { @@ -91,13 +106,6 @@ func NewSymBandDense(n, k int, data []float64) *SymBandDense { } } -// NewDiagonal is a convenience function that returns a diagonal matrix represented by a -// SymBandDense. The length of data must be n or data must be nil, otherwise NewDiagonal -// will panic. -func NewDiagonal(n int, data []float64) *SymBandDense { - return NewSymBandDense(n, 0, data) -} - // Dims returns the number of rows and columns in the matrix. func (s *SymBandDense) Dims() (r, c int) { return s.mat.N, s.mat.N @@ -113,6 +121,12 @@ func (s *SymBandDense) Bandwidth() (kl, ku int) { return s.mat.K, s.mat.K } +// SymBand returns the number of rows/columns in the matrix, and the size of +// the bandwidth. +func (s *SymBandDense) SymBand() (n, k int) { + return s.mat.N, s.mat.K +} + // T implements the Matrix interface. Symmetric matrices, by definition, are // equal to their transpose, and this is a no-op. func (s *SymBandDense) T() Matrix { @@ -131,6 +145,38 @@ func (s *SymBandDense) RawSymBand() blas64.SymmetricBand { return s.mat } +// SetRawSymBand sets the underlying blas64.SymmetricBand used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in the input. +// +// The supplied SymmetricBand must use blas.Upper storage format. +func (s *SymBandDense) SetRawSymBand(mat blas64.SymmetricBand) { + if mat.Uplo != blas.Upper { + panic("mat: blas64.SymmetricBand does not have blas.Upper storage") + } + s.mat = mat +} + +// Zero sets all of the matrix elements to zero. +func (s *SymBandDense) Zero() { + for i := 0; i < s.mat.N; i++ { + u := min(1+s.mat.K, s.mat.N-i) + zero(s.mat.Data[i*s.mat.Stride : i*s.mat.Stride+u]) + } +} + +// DiagView returns the diagonal as a matrix backed by the original data. +func (s *SymBandDense) DiagView() Diagonal { + n := s.mat.N + return &DiagDense{ + mat: blas64.Vector{ + N: n, + Inc: s.mat.Stride, + Data: s.mat.Data[:(n-1)*s.mat.Stride+1], + }, + } +} + // DoNonZero calls the function fn for each of the non-zero elements of s. The function fn // takes a row/column index and the element value of s at (i, j). func (s *SymBandDense) DoNonZero(fn func(i, j int, v float64)) { diff --git a/vendor/gonum.org/v1/gonum/mat/symmetric.go b/vendor/gonum.org/v1/gonum/mat/symmetric.go index d3ac2617737..2ea5bdb0392 100644 --- a/vendor/gonum.org/v1/gonum/mat/symmetric.go +++ b/vendor/gonum.org/v1/gonum/mat/symmetric.go @@ -55,12 +55,16 @@ type MutableSymmetric interface { // 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. +// NewSymDense will panic if n is zero. // // 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 { + if n <= 0 { + if n == 0 { + panic(ErrZeroLength) + } panic("mat: negative dimension") } if data != nil && n*n != len(data) { @@ -90,12 +94,13 @@ func (s *SymDense) Caps() (r, c int) { return s.cap, s.cap } -// T implements the Matrix interface. Symmetric matrices, by definition, are -// equal to their transpose, and this is a no-op. +// T returns the receiver, the transpose of a symmetric matrix. func (s *SymDense) T() Matrix { return s } +// Symmetric implements the Symmetric interface and returns the number of rows +// and columns in the matrix. func (s *SymDense) Symmetric() int { return s.mat.N } @@ -108,13 +113,14 @@ func (s *SymDense) RawSymmetric() blas64.Symmetric { // 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 { +// in the input. +// +// The supplied Symmetric must use blas.Upper storage format. +func (s *SymDense) SetRawSymmetric(mat blas64.Symmetric) { + if mat.Uplo != blas.Upper { panic(badSymTriangle) } - s.mat = b + s.mat = mat } // Reset zeros the dimensions of the matrix so that it can be reused as the @@ -127,6 +133,13 @@ func (s *SymDense) Reset() { s.mat.Data = s.mat.Data[:0] } +// Zero sets all of the matrix elements to zero. +func (s *SymDense) Zero() { + for i := 0; i < s.mat.N; i++ { + zero(s.mat.Data[i*s.mat.Stride+i : i*s.mat.Stride+s.mat.N]) + } +} + // IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the // receiver for size-restricted operations. SymDense matrices can be zeroed using Reset. func (s *SymDense) IsZero() bool { @@ -174,6 +187,18 @@ func (s *SymDense) isolatedWorkspace(a Symmetric) (w *SymDense, restore func()) } } +// DiagView returns the diagonal as a matrix backed by the original data. +func (s *SymDense) DiagView() Diagonal { + n := s.mat.N + return &DiagDense{ + mat: blas64.Vector{ + N: n, + Inc: s.mat.Stride + 1, + Data: s.mat.Data[:(n-1)*s.mat.Stride+n], + }, + } +} + func (s *SymDense) AddSym(a, b Symmetric) { n := a.Symmetric() if n != b.Symmetric() { @@ -257,7 +282,7 @@ func (s *SymDense) SymRankOne(a Symmetric, alpha float64, x Vector) { xU, _ := untranspose(x) if rv, ok := xU.(RawVectorer); ok { xmat := rv.RawVector() - s.checkOverlap((&VecDense{mat: xmat, n: n}).asGeneral()) + s.checkOverlap((&VecDense{mat: xmat}).asGeneral()) blas64.Syr(alpha, xmat, s.mat) return } @@ -371,14 +396,14 @@ func (s *SymDense) RankTwo(a Symmetric, alpha float64, x, y Vector) { xU, _ := untranspose(x) if rv, ok := xU.(RawVectorer); ok { xmat = rv.RawVector() - s.checkOverlap((&VecDense{mat: xmat, n: x.Len()}).asGeneral()) + s.checkOverlap((&VecDense{mat: xmat}).asGeneral()) } else { fast = false } yU, _ := untranspose(y) if rv, ok := yU.(RawVectorer); ok { ymat = rv.RawVector() - s.checkOverlap((&VecDense{mat: ymat, n: y.Len()}).asGeneral()) + s.checkOverlap((&VecDense{mat: ymat}).asGeneral()) } else { fast = false } @@ -473,12 +498,12 @@ func (s *SymDense) SubsetSym(a Symmetric, set []int) { } } -// SliceSquare returns a new Matrix that shares backing data with the receiver. +// SliceSym returns a new Matrix that shares backing data with the receiver. // The returned matrix starts at {i,i} of the receiver 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 capacity -// of the receiver. -func (s *SymDense) SliceSquare(i, k int) Matrix { +// SliceSym panics with ErrIndexOutOfRange if the slice is outside the +// capacity of the receiver. +func (s *SymDense) SliceSym(i, k int) Symmetric { sz := s.cap if i < 0 || sz < i || k < i || sz < k { panic(ErrIndexOutOfRange) @@ -490,11 +515,21 @@ func (s *SymDense) SliceSquare(i, k int) Matrix { return &v } -// GrowSquare returns the receiver expanded by n rows and n columns. If the +// Trace returns the trace of the matrix. +func (s *SymDense) Trace() float64 { + // TODO(btracey): could use internal asm sum routine. + var v float64 + for i := 0; i < s.mat.N; i++ { + v += s.mat.Data[i*s.mat.Stride+i] + } + return v +} + +// GrowSym 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 { +func (s *SymDense) GrowSym(n int) Symmetric { if n < 0 { panic(ErrIndexOutOfRange) } @@ -554,14 +589,13 @@ func (s *SymDense) PowPSD(a Symmetric, pow float64) error { } values[i] = math.Pow(v, pow) } - var u Dense - u.EigenvectorsSym(&eigen) + u := eigen.VectorsTo(nil) s.SymOuterK(values[0], u.ColView(0)) var v VecDense for i := 1; i < dim; i++ { - v.ColViewOf(&u, i) + v.ColViewOf(u, i) s.SymRankOne(s, values[i], &v) } return nil diff --git a/vendor/gonum.org/v1/gonum/mat/triangular.go b/vendor/gonum.org/v1/gonum/mat/triangular.go index c4446b55950..e32ee405498 100644 --- a/vendor/gonum.org/v1/gonum/mat/triangular.go +++ b/vendor/gonum.org/v1/gonum/mat/triangular.go @@ -36,7 +36,7 @@ type TriDense struct { // Triangular represents a triangular matrix. Triangular matrices are always square. type Triangular interface { Matrix - // Triangular returns the number of rows/columns in the matrix and its + // Triangle returns the number of rows/columns in the matrix and its // orientation. Triangle() (n int, kind TriKind) @@ -45,7 +45,9 @@ type Triangular interface { TTri() Triangular } -// A RawTriangular can return a view of itself as a BLAS Triangular matrix. +// A RawTriangular can return a blas64.Triangular representation of the receiver. +// Changes to the blas64.Triangular.Data slice will be reflected in the original +// matrix, changes to the N, Stride, Uplo and Diag fields will not. type RawTriangular interface { RawTriangular() blas64.Triangular } @@ -111,12 +113,16 @@ func (t TransposeTri) UntransposeTri() Triangular { // 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. +// NewTriDense will panic if n is zero. // // 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 TriKind, data []float64) *TriDense { - if n < 0 { + if n <= 0 { + if n == 0 { + panic(ErrZeroLength) + } panic("mat: negative dimension") } if data != nil && len(data) != n*n { @@ -148,7 +154,7 @@ func (t *TriDense) Dims() (r, c int) { // 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 TriKind) { - return t.mat.N, TriKind(!t.IsZero()) && t.triKind() + return t.mat.N, t.triKind() } func (t *TriDense) isUpper() bool { @@ -170,6 +176,17 @@ func isUpperUplo(u blas.Uplo) bool { } } +func uploToTriKind(u blas.Uplo) TriKind { + switch u { + case blas.Upper: + return Upper + case blas.Lower: + return Lower + 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 @@ -200,6 +217,18 @@ func (t *TriDense) RawTriangular() blas64.Triangular { return t.mat } +// SetRawTriangular sets the underlying blas64.Triangular used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in the input. +// +// The supplied Triangular must not use blas.Unit storage format. +func (t *TriDense) SetRawTriangular(mat blas64.Triangular) { + if mat.Diag == blas.Unit { + panic("mat: cannot set TriDense with Unit storage format") + } + t.mat = mat +} + // Reset zeros the dimensions of the matrix so that it can be reused as the // receiver of a dimensionally restricted operation. // @@ -213,6 +242,19 @@ func (t *TriDense) Reset() { t.mat.Data = t.mat.Data[:0] } +// Zero sets all of the matrix elements to zero. +func (t *TriDense) Zero() { + if t.isUpper() { + for i := 0; i < t.mat.N; i++ { + zero(t.mat.Data[i*t.mat.Stride+i : i*t.mat.Stride+t.mat.N]) + } + return + } + for i := 0; i < t.mat.N; i++ { + zero(t.mat.Data[i*t.mat.Stride : i*t.mat.Stride+i+1]) + } +} + // IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the // receiver for size-restricted operations. TriDense matrices can be zeroed using Reset. func (t *TriDense) IsZero() bool { @@ -279,6 +321,21 @@ func (t *TriDense) isolatedWorkspace(a Triangular) (w *TriDense, restore func()) } } +// DiagView returns the diagonal as a matrix backed by the original data. +func (t *TriDense) DiagView() Diagonal { + if t.mat.Diag == blas.Unit { + panic("mat: cannot take view of Unit diagonal") + } + n := t.mat.N + return &DiagDense{ + mat: blas64.Vector{ + N: n, + Inc: t.mat.Stride + 1, + Data: t.mat.Data[:(n-1)*t.mat.Stride+n], + }, + } +} + // 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 @@ -468,6 +525,16 @@ func (t *TriDense) ScaleTri(f float64, a Triangular) { } } +// Trace returns the trace of the matrix. +func (t *TriDense) Trace() float64 { + // TODO(btracey): could use internal asm sum routine. + var v float64 + for i := 0; i < t.mat.N; i++ { + v += t.mat.Data[i*t.mat.Stride+i] + } + return v +} + // copySymIntoTriangle copies a symmetric matrix into a TriDense func copySymIntoTriangle(t *TriDense, s Symmetric) { n, upper := t.Triangle() diff --git a/vendor/gonum.org/v1/gonum/mat/triband.go b/vendor/gonum.org/v1/gonum/mat/triband.go new file mode 100644 index 00000000000..f97855046ea --- /dev/null +++ b/vendor/gonum.org/v1/gonum/mat/triband.go @@ -0,0 +1,353 @@ +// Copyright ©2018 The Gonum Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mat + +import ( + "gonum.org/v1/gonum/blas" + "gonum.org/v1/gonum/blas/blas64" +) + +var ( + triBand TriBanded + _ Banded = triBand + _ Triangular = triBand + + triBandDense *TriBandDense + _ Matrix = triBandDense + _ Triangular = triBandDense + _ Banded = triBandDense + _ TriBanded = triBandDense + _ RawTriBander = triBandDense + _ MutableTriBanded = triBandDense +) + +// TriBanded is a triangular band matrix interface type. +type TriBanded interface { + Banded + + // Triangle returns the number of rows/columns in the matrix and its + // orientation. + Triangle() (n int, kind TriKind) + + // TTri is the equivalent of the T() method in the Matrix interface but + // guarantees the transpose is of triangular type. + TTri() Triangular + + // TriBand returns the number of rows/columns in the matrix, the + // size of the bandwidth, and the orientation. + TriBand() (n, k int, kind TriKind) + + // TTriBand is the equivalent of the T() method in the Matrix interface but + // guarantees the transpose is of banded triangular type. + TTriBand() TriBanded +} + +// A RawTriBander can return a blas64.TriangularBand representation of the receiver. +// Changes to the blas64.TriangularBand.Data slice will be reflected in the original +// matrix, changes to the N, K, Stride, Uplo and Diag fields will not. +type RawTriBander interface { + RawTriBand() blas64.TriangularBand +} + +// MutableTriBanded is a triangular band matrix interface type that allows +// elements to be altered. +type MutableTriBanded interface { + TriBanded + SetTriBand(i, j int, v float64) +} + +var ( + tTriBand TransposeTriBand + _ Matrix = tTriBand + _ TriBanded = tTriBand + _ Untransposer = tTriBand + _ UntransposeTrier = tTriBand + _ UntransposeBander = tTriBand + _ UntransposeTriBander = tTriBand +) + +// TransposeTriBand is a type for performing an implicit transpose of a TriBanded +// matrix. It implements the TriBanded interface, returning values from the +// transpose of the matrix within. +type TransposeTriBand struct { + TriBanded TriBanded +} + +// 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 TriBanded field. +func (t TransposeTriBand) At(i, j int) float64 { + return t.TriBanded.At(j, i) +} + +// Dims returns the dimensions of the transposed matrix. TriBanded matrices are +// square and thus this is the same size as the original TriBanded. +func (t TransposeTriBand) Dims() (r, c int) { + c, r = t.TriBanded.Dims() + return r, c +} + +// T performs an implicit transpose by returning the TriBand field. +func (t TransposeTriBand) T() Matrix { + return t.TriBanded +} + +// Triangle returns the number of rows/columns in the matrix and its orientation. +func (t TransposeTriBand) Triangle() (int, TriKind) { + n, upper := t.TriBanded.Triangle() + return n, !upper +} + +// TTri performs an implicit transpose by returning the TriBand field. +func (t TransposeTriBand) TTri() Triangular { + return t.TriBanded +} + +// Bandwidth returns the upper and lower bandwidths of the matrix. +func (t TransposeTriBand) Bandwidth() (kl, ku int) { + kl, ku = t.TriBanded.Bandwidth() + return ku, kl +} + +// TBand performs an implicit transpose by returning the TriBand field. +func (t TransposeTriBand) TBand() Banded { + return t.TriBanded +} + +// TriBand returns the number of rows/columns in the matrix, the +// size of the bandwidth, and the orientation. +func (t TransposeTriBand) TriBand() (n, k int, kind TriKind) { + n, k, kind = t.TriBanded.TriBand() + return n, k, !kind +} + +// TTriBand performs an implicit transpose by returning the TriBand field. +func (t TransposeTriBand) TTriBand() TriBanded { + return t.TriBanded +} + +// Untranspose returns the Triangular field. +func (t TransposeTriBand) Untranspose() Matrix { + return t.TriBanded +} + +// UntransposeTri returns the underlying Triangular matrix. +func (t TransposeTriBand) UntransposeTri() Triangular { + return t.TriBanded +} + +// UntransposeBand returns the underlying Banded matrix. +func (t TransposeTriBand) UntransposeBand() Banded { + return t.TriBanded +} + +// UntransposeTriBand returns the underlying TriBanded matrix. +func (t TransposeTriBand) UntransposeTriBand() TriBanded { + return t.TriBanded +} + +// TriBandDense represents a triangular band matrix in dense storage format. +type TriBandDense struct { + mat blas64.TriangularBand +} + +// NewTriBandDense creates a new triangular banded matrix with n rows and columns, +// k bands in the direction of the specified kind. If data == nil, +// a new slice is allocated for the backing slice. If len(data) == n*(k+1), +// data is used as the backing slice, and changes to the elements of the returned +// TriBandDense will be reflected in data. If neither of these is true, NewTriBandDense +// will panic. k must be at least zero and less than n, otherwise NewTriBandDense will panic. +// +// The data must be arranged in row-major order constructed by removing the zeros +// from the rows outside the band and aligning the diagonals. For example, if +// the upper-triangular banded matrix +// 1 2 3 0 0 0 +// 0 4 5 6 0 0 +// 0 0 7 8 9 0 +// 0 0 0 10 11 12 +// 0 0 0 0 13 14 +// 0 0 0 0 0 15 +// becomes (* entries are never accessed) +// 1 2 3 +// 4 5 6 +// 7 8 9 +// 10 11 12 +// 13 14 * +// 15 * * +// which is passed to NewTriBandDense as []float64{1, 2, ..., 15, *, *, *} +// with k=2 and kind = mat.Upper. +// The lower triangular banded matrix +// 1 0 0 0 0 0 +// 2 3 0 0 0 0 +// 4 5 6 0 0 0 +// 0 7 8 9 0 0 +// 0 0 10 11 12 0 +// 0 0 0 13 14 15 +// becomes (* entries are never accessed) +// * * 1 +// * 2 3 +// 4 5 6 +// 7 8 9 +// 10 11 12 +// 13 14 15 +// which is passed to NewTriBandDense as []float64{*, *, *, 1, 2, ..., 15} +// with k=2 and kind = mat.Lower. +// Only the values in the band portion of the matrix are used. +func NewTriBandDense(n, k int, kind TriKind, data []float64) *TriBandDense { + if n <= 0 || k < 0 { + if n == 0 { + panic(ErrZeroLength) + } + panic("mat: negative dimension") + } + if k+1 > n { + panic("mat: band out of range") + } + bc := k + 1 + if data != nil && len(data) != n*bc { + panic(ErrShape) + } + if data == nil { + data = make([]float64, n*bc) + } + uplo := blas.Lower + if kind { + uplo = blas.Upper + } + return &TriBandDense{ + mat: blas64.TriangularBand{ + Uplo: uplo, + Diag: blas.NonUnit, + N: n, + K: k, + Data: data, + Stride: bc, + }, + } +} + +// Dims returns the number of rows and columns in the matrix. +func (t *TriBandDense) Dims() (r, c int) { + return t.mat.N, t.mat.N +} + +// T performs an implicit transpose by returning the receiver inside a Transpose. +func (t *TriBandDense) T() Matrix { + return Transpose{t} +} + +// IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the +// receiver for size-restricted operations. TriBandDense matrices can be zeroed using Reset. +func (t *TriBandDense) IsZero() bool { + // It must be the case that t.Dims() returns + // zeros in this case. See comment in Reset(). + return t.mat.Stride == 0 +} + +// 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 *TriBandDense) Reset() { + t.mat.N = 0 + t.mat.Stride = 0 + t.mat.K = 0 + t.mat.Data = t.mat.Data[:0] +} + +// Zero sets all of the matrix elements to zero. +func (t *TriBandDense) Zero() { + if t.isUpper() { + for i := 0; i < t.mat.N; i++ { + u := min(1+t.mat.K, t.mat.N-i) + zero(t.mat.Data[i*t.mat.Stride : i*t.mat.Stride+u]) + } + return + } + for i := 0; i < t.mat.N; i++ { + l := max(0, t.mat.K-i) + zero(t.mat.Data[i*t.mat.Stride+l : i*t.mat.Stride+t.mat.K+1]) + } +} + +func (t *TriBandDense) isUpper() bool { + return isUpperUplo(t.mat.Uplo) +} + +func (t *TriBandDense) triKind() TriKind { + return TriKind(isUpperUplo(t.mat.Uplo)) +} + +// Triangle returns the dimension of t and its orientation. The returned +// orientation is only valid when n is not zero. +func (t *TriBandDense) Triangle() (n int, kind TriKind) { + return t.mat.N, t.triKind() +} + +// TTri performs an implicit transpose by returning the receiver inside a TransposeTri. +func (t *TriBandDense) TTri() Triangular { + return TransposeTri{t} +} + +// Bandwidth returns the upper and lower bandwidths of the matrix. +func (t *TriBandDense) Bandwidth() (kl, ku int) { + if t.isUpper() { + return 0, t.mat.K + } + return t.mat.K, 0 +} + +// TBand performs an implicit transpose by returning the receiver inside a TransposeBand. +func (t *TriBandDense) TBand() Banded { + return TransposeBand{t} +} + +// TriBand returns the number of rows/columns in the matrix, the +// size of the bandwidth, and the orientation. +func (t *TriBandDense) TriBand() (n, k int, kind TriKind) { + return t.mat.N, t.mat.K, TriKind(!t.IsZero()) && t.triKind() +} + +// TTriBand performs an implicit transpose by returning the receiver inside a TransposeTriBand. +func (t *TriBandDense) TTriBand() TriBanded { + return TransposeTriBand{t} +} + +// RawTriBand returns the underlying blas64.TriangularBand used by the receiver. +// Changes to the blas64.TriangularBand.Data slice will be reflected in the original +// matrix, changes to the N, K, Stride, Uplo and Diag fields will not. +func (t *TriBandDense) RawTriBand() blas64.TriangularBand { + return t.mat +} + +// SetRawTriBand sets the underlying blas64.TriangularBand used by the receiver. +// Changes to elements in the receiver following the call will be reflected +// in the input. +// +// The supplied TriangularBand must not use blas.Unit storage format. +func (t *TriBandDense) SetRawTriBand(mat blas64.TriangularBand) { + if mat.Diag == blas.Unit { + panic("mat: cannot set TriBand with Unit storage") + } + t.mat = mat +} + +// DiagView returns the diagonal as a matrix backed by the original data. +func (t *TriBandDense) DiagView() Diagonal { + if t.mat.Diag == blas.Unit { + panic("mat: cannot take view of Unit diagonal") + } + n := t.mat.N + data := t.mat.Data + if !t.isUpper() { + data = data[t.mat.K:] + } + return &DiagDense{ + mat: blas64.Vector{ + N: n, + Inc: t.mat.Stride, + Data: data[:(n-1)*t.mat.Stride+1], + }, + } +} diff --git a/vendor/gonum.org/v1/gonum/mat/vector.go b/vendor/gonum.org/v1/gonum/mat/vector.go index ca29e5035a9..8191312bfe4 100644 --- a/vendor/gonum.org/v1/gonum/mat/vector.go +++ b/vendor/gonum.org/v1/gonum/mat/vector.go @@ -76,7 +76,6 @@ func (t TransposeVec) UntransposeVec() Vector { // VecDense represents a column vector. type VecDense struct { mat blas64.Vector - n int // A BLAS vector can have a negative increment, but allowing this // in the mat type complicates a lot of code, and doesn't gain anything. // VecDense must have positive increment in this package. @@ -86,8 +85,12 @@ type VecDense struct { // 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 VecDense // will be reflected in data. If neither of these is true, NewVecDense will panic. +// NewVecDense will panic if n is zero. func NewVecDense(n int, data []float64) *VecDense { - if n < 0 { + if n <= 0 { + if n == 0 { + panic(ErrZeroLength) + } panic("mat: negative dimension") } if len(data) != n && data != nil { @@ -98,10 +101,10 @@ func NewVecDense(n int, data []float64) *VecDense { } return &VecDense{ mat: blas64.Vector{ + N: n, Inc: 1, Data: data, }, - n: n, } } @@ -114,8 +117,8 @@ func (v *VecDense) SliceVec(i, k int) Vector { panic(ErrIndexOutOfRange) } return &VecDense{ - n: k - i, mat: blas64.Vector{ + N: k - i, Inc: v.mat.Inc, Data: v.mat.Data[i*v.mat.Inc : (k-1)*v.mat.Inc+1], }, @@ -128,7 +131,7 @@ func (v *VecDense) Dims() (r, c int) { if v.IsZero() { return 0, 0 } - return v.n, 1 + return v.mat.N, 1 } // Caps returns the number of rows and columns in the backing matrix. Columns is always 1 @@ -142,7 +145,7 @@ func (v *VecDense) Caps() (r, c int) { // Len returns the length of the vector. func (v *VecDense) Len() int { - return v.n + return v.mat.N } // Cap returns the capacity of the vector. @@ -168,26 +171,34 @@ func (v *VecDense) TVec() Vector { // // See the Reseter interface for more information. func (v *VecDense) Reset() { - // No change of Inc or n to 0 may be + // 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.N = 0 v.mat.Data = v.mat.Data[:0] } +// Zero sets all of the matrix elements to zero. +func (v *VecDense) Zero() { + for i := 0; i < v.mat.N; i++ { + v.mat.Data[v.mat.Inc*i] = 0 + } +} + // CloneVec makes a copy of a into the receiver, overwriting the previous value // of the receiver. func (v *VecDense) CloneVec(a Vector) { if v == a { return } - v.n = a.Len() + n := a.Len() v.mat = blas64.Vector{ + N: n, Inc: 1, - Data: use(v.mat.Data, v.n), + Data: use(v.mat.Data, n), } if r, ok := a.(RawVectorer); ok { - blas64.Copy(v.n, r.RawVector(), v.mat) + blas64.Copy(r.RawVector(), v.mat) return } for i := 0; i < a.Len(); i++ { @@ -215,7 +226,7 @@ func (v *VecDense) CopyVec(a Vector) int { return n } if r, ok := a.(RawVectorer); ok { - blas64.Copy(n, r.RawVector(), v.mat) + blas64.Copy(r.RawVector(), v.mat) return n } for i := 0; i < n; i++ { @@ -304,7 +315,7 @@ func (v *VecDense) AddScaledVec(a Vector, alpha float64, b Vector) { } v.CopyVec(a) case v == a && v == b: // v <- v + alpha * v = (alpha + 1) * v - blas64.Scal(ar, alpha+1, v.mat) + blas64.Scal(alpha+1, v.mat) case !fast: // v <- a + alpha * b without blas64 support. for i := 0; i < ar; i++ { v.setVec(i, a.AtVec(i)+alpha*b.AtVec(i)) @@ -641,13 +652,13 @@ func (v *VecDense) reuseAs(r int) { } if v.IsZero() { v.mat = blas64.Vector{ + N: r, Inc: 1, Data: use(v.mat.Data, r), } - v.n = r return } - if r != v.n { + if r != v.mat.N { panic(ErrShape) } } @@ -677,7 +688,7 @@ func (v *VecDense) isolatedWorkspace(a Vector) (n *VecDense, restore func()) { func (v *VecDense) asDense() *Dense { return &Dense{ mat: v.asGeneral(), - capRows: v.n, + capRows: v.mat.N, capCols: 1, } } @@ -686,7 +697,7 @@ func (v *VecDense) asDense() *Dense { // same underlying data. func (v *VecDense) asGeneral() blas64.General { return blas64.General{ - Rows: v.n, + Rows: v.mat.N, Cols: 1, Stride: v.mat.Inc, Data: v.mat.Data, @@ -702,13 +713,13 @@ func (v *VecDense) ColViewOf(m RawMatrixer, j int) { if j >= rm.Cols || j < 0 { panic(ErrColAccess) } - if !v.IsZero() && v.n != rm.Rows { + if !v.IsZero() && v.mat.N != rm.Rows { panic(ErrShape) } v.mat.Inc = rm.Stride v.mat.Data = rm.Data[j : (rm.Rows-1)*rm.Stride+j+1] - v.n = rm.Rows + v.mat.N = rm.Rows } // RowViewOf reflects the row i of the RawMatrixer m, into the receiver @@ -720,11 +731,11 @@ func (v *VecDense) RowViewOf(m RawMatrixer, i int) { if i >= rm.Rows || i < 0 { panic(ErrRowAccess) } - if !v.IsZero() && v.n != rm.Cols { + if !v.IsZero() && v.mat.N != rm.Cols { panic(ErrShape) } v.mat.Inc = 1 v.mat.Data = rm.Data[i*rm.Stride : i*rm.Stride+rm.Cols] - v.n = rm.Cols + v.mat.N = rm.Cols } diff --git a/vendor/modules.txt b/vendor/modules.txt index dd0c7e2e34e..c66590e0599 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -995,9 +995,10 @@ golang.org/x/tools/internal/fastwalk golang.org/x/tools/internal/gopathwalk golang.org/x/tools/internal/module golang.org/x/tools/internal/semver -# gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 => gonum.org/v1/gonum v0.0.0-20180726124543-cebdade430cc +# gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 => gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 gonum.org/v1/gonum/blas gonum.org/v1/gonum/blas/blas64 +gonum.org/v1/gonum/blas/cblas128 gonum.org/v1/gonum/blas/gonum gonum.org/v1/gonum/floats gonum.org/v1/gonum/graph @@ -1014,12 +1015,15 @@ gonum.org/v1/gonum/graph/internal/linear gonum.org/v1/gonum/graph/internal/ordered gonum.org/v1/gonum/graph/internal/set gonum.org/v1/gonum/graph/internal/uid +gonum.org/v1/gonum/graph/iterator gonum.org/v1/gonum/graph/simple gonum.org/v1/gonum/graph/topo gonum.org/v1/gonum/graph/traverse gonum.org/v1/gonum/internal/asm/c128 +gonum.org/v1/gonum/internal/asm/c64 gonum.org/v1/gonum/internal/asm/f32 gonum.org/v1/gonum/internal/asm/f64 +gonum.org/v1/gonum/internal/cmplx64 gonum.org/v1/gonum/internal/math32 gonum.org/v1/gonum/lapack gonum.org/v1/gonum/lapack/gonum