OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / gonum.org / v1 / gonum / lapack / gonum / dtrevc3.go
diff --git a/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go b/vendor/gonum.org/v1/gonum/lapack/gonum/dtrevc3.go
deleted file mode 100644 (file)
index 200bf17..0000000
+++ /dev/null
@@ -1,866 +0,0 @@
-// Copyright ©2016 The Gonum Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package gonum
-
-import (
-       "math"
-
-       "gonum.org/v1/gonum/blas"
-       "gonum.org/v1/gonum/blas/blas64"
-       "gonum.org/v1/gonum/lapack"
-)
-
-// Dtrevc3 computes some or all of the right and/or left eigenvectors of an n×n
-// upper quasi-triangular matrix T in Schur canonical form. Matrices of this
-// type are produced by the Schur factorization of a real general matrix A
-//  A = Q T Q^T,
-// as computed by Dhseqr.
-//
-// The right eigenvector x of T corresponding to an
-// eigenvalue λ is defined by
-//  T x = λ x,
-// and the left eigenvector is defined by
-//  y^H T = λ y^H,
-// where y^H is the conjugate transpose of y.
-//
-// The eigenvalues are read directly from the diagonal blocks of T.
-//
-// This routine returns the matrices X and/or Y of right and left eigenvectors
-// of T, or the products Q*X and/or Q*Y, where Q is an input matrix. If Q is the
-// orthogonal factor that reduces a matrix A to Schur form T, then Q*X and Q*Y
-// are the matrices of right and left eigenvectors of A.
-//
-// If side == lapack.RightEV, only right eigenvectors will be computed.
-// If side == lapack.LeftEV, only left eigenvectors will be computed.
-// If side == lapack.RightLeftEV, both right and left eigenvectors will be computed.
-// For other values of side, Dtrevc3 will panic.
-//
-// If howmny == lapack.AllEV, all right and/or left eigenvectors will be
-// computed.
-// If howmny == lapack.AllEVMulQ, all right and/or left eigenvectors will be
-// computed and multiplied from left by the matrices in VR and/or VL.
-// If howmny == lapack.SelectedEV, right and/or left eigenvectors will be
-// computed as indicated by selected.
-// For other values of howmny, Dtrevc3 will panic.
-//
-// selected specifies which eigenvectors will be computed. It must have length n
-// if howmny == lapack.SelectedEV, and it is not referenced otherwise.
-// If w_j is a real eigenvalue, the corresponding real eigenvector will be
-// computed if selected[j] is true.
-// If w_j and w_{j+1} are the real and imaginary parts of a complex eigenvalue,
-// the corresponding complex eigenvector is computed if either selected[j] or
-// selected[j+1] is true, and on return selected[j] will be set to true and
-// selected[j+1] will be set to false.
-//
-// VL and VR are n×mm matrices. If howmny is lapack.AllEV or
-// lapack.AllEVMulQ, mm must be at least n. If howmny ==
-// lapack.SelectedEV, mm must be large enough to store the selected
-// eigenvectors. Each selected real eigenvector occupies one column and each
-// selected complex eigenvector occupies two columns. If mm is not sufficiently
-// large, Dtrevc3 will panic.
-//
-// On entry, if howmny == lapack.AllEVMulQ, it is assumed that VL (if side
-// is lapack.LeftEV or lapack.RightLeftEV) contains an n×n matrix QL,
-// and that VR (if side is lapack.LeftEV or lapack.RightLeftEV) contains
-// an n×n matrix QR. QL and QR are typically the orthogonal matrix Q of Schur
-// vectors returned by Dhseqr.
-//
-// On return, if side is lapack.LeftEV or lapack.RightLeftEV,
-// VL will contain:
-//  if howmny == lapack.AllEV,      the matrix Y of left eigenvectors of T,
-//  if howmny == lapack.AllEVMulQ,  the matrix Q*Y,
-//  if howmny == lapack.SelectedEV, the left eigenvectors of T specified by
-//                                  selected, stored consecutively in the
-//                                  columns of VL, in the same order as their
-//                                  eigenvalues.
-// VL is not referenced if side == lapack.RightEV.
-//
-// On return, if side is lapack.RightEV or lapack.RightLeftEV,
-// VR will contain:
-//  if howmny == lapack.AllEV,      the matrix X of right eigenvectors of T,
-//  if howmny == lapack.AllEVMulQ,  the matrix Q*X,
-//  if howmny == lapack.SelectedEV, the left eigenvectors of T specified by
-//                                  selected, stored consecutively in the
-//                                  columns of VR, in the same order as their
-//                                  eigenvalues.
-// VR is not referenced if side == lapack.LeftEV.
-//
-// Complex eigenvectors corresponding to a complex eigenvalue are stored in VL
-// and VR in two consecutive columns, the first holding the real part, and the
-// second the imaginary part.
-//
-// Each eigenvector will be normalized so that the element of largest magnitude
-// has magnitude 1. Here the magnitude of a complex number (x,y) is taken to be
-// |x| + |y|.
-//
-// work must have length at least lwork and lwork must be at least max(1,3*n),
-// otherwise Dtrevc3 will panic. For optimum performance, lwork should be at
-// least n+2*n*nb, where nb is the optimal blocksize.
-//
-// If lwork == -1, instead of performing Dtrevc3, the function only estimates
-// the optimal workspace size based on n and stores it into work[0].
-//
-// Dtrevc3 returns the number of columns in VL and/or VR actually used to store
-// the eigenvectors.
-//
-// Dtrevc3 is an internal routine. It is exported for testing purposes.
-func (impl Implementation) Dtrevc3(side lapack.EVSide, howmny lapack.HowMany, selected []bool, n int, t []float64, ldt int, vl []float64, ldvl int, vr []float64, ldvr int, mm int, work []float64, lwork int) (m int) {
-       switch side {
-       default:
-               panic(badEVSide)
-       case lapack.RightEV, lapack.LeftEV, lapack.RightLeftEV:
-       }
-       switch howmny {
-       default:
-               panic(badHowMany)
-       case lapack.AllEV, lapack.AllEVMulQ, lapack.SelectedEV:
-       }
-       switch {
-       case n < 0:
-               panic(nLT0)
-       case len(work) < lwork:
-               panic(shortWork)
-       case lwork < max(1, 3*n) && lwork != -1:
-               panic(badWork)
-       }
-       if lwork != -1 {
-               if howmny == lapack.SelectedEV {
-                       if len(selected) != n {
-                               panic("lapack: bad selected length")
-                       }
-                       // Set m to the number of columns required to store the
-                       // selected eigenvectors, and standardize the slice
-                       // selected.
-                       for j := 0; j < n; {
-                               if j == n-1 || t[(j+1)*ldt+j] == 0 {
-                                       // Diagonal 1×1 block corresponding to a
-                                       // real eigenvalue.
-                                       if selected[j] {
-                                               m++
-                                       }
-                                       j++
-                               } else {
-                                       // Diagonal 2×2 block corresponding to a
-                                       // complex eigenvalue.
-                                       if selected[j] || selected[j+1] {
-                                               selected[j] = true
-                                               selected[j+1] = false
-                                               m += 2
-                                       }
-                                       j += 2
-                               }
-                       }
-               } else {
-                       m = n
-               }
-               if m > mm {
-                       panic("lapack: insufficient number of columns")
-               }
-               checkMatrix(n, n, t, ldt)
-               if (side == lapack.RightEV || side == lapack.RightLeftEV) && m > 0 {
-                       checkMatrix(n, m, vr, ldvr)
-               }
-               if (side == lapack.LeftEV || side == lapack.RightLeftEV) && m > 0 {
-                       checkMatrix(n, m, vl, ldvl)
-               }
-       }
-
-       // Quick return if possible.
-       if n == 0 {
-               work[0] = 1
-               return m
-       }
-
-       const (
-               nbmin = 8
-               nbmax = 128
-       )
-       nb := impl.Ilaenv(1, "DTREVC", string(side)+string(howmny), n, -1, -1, -1)
-
-       // Quick return in case of a workspace query.
-       if lwork == -1 {
-               work[0] = float64(n + 2*n*nb)
-               return m
-       }
-
-       // Use blocked version of back-transformation if sufficient workspace.
-       // Zero-out the workspace to avoid potential NaN propagation.
-       if howmny == lapack.AllEVMulQ && lwork >= n+2*n*nbmin {
-               nb = min((lwork-n)/(2*n), nbmax)
-               impl.Dlaset(blas.All, n, 1+2*nb, 0, 0, work[:n+2*nb*n], 1+2*nb)
-       } else {
-               nb = 1
-       }
-
-       // Set the constants to control overflow.
-       ulp := dlamchP
-       smlnum := float64(n) / ulp * dlamchS
-       bignum := (1 - ulp) / smlnum
-
-       // Split work into a vector of column norms and an n×2*nb matrix b.
-       norms := work[:n]
-       ldb := 2 * nb
-       b := work[n : n+n*ldb]
-
-       // Compute 1-norm of each column of strictly upper triangular part of T
-       // to control overflow in triangular solver.
-       norms[0] = 0
-       for j := 1; j < n; j++ {
-               var cn float64
-               for i := 0; i < j; i++ {
-                       cn += math.Abs(t[i*ldt+j])
-               }
-               norms[j] = cn
-       }
-
-       bi := blas64.Implementation()
-
-       var (
-               x [4]float64
-
-               iv int // Index of column in current block.
-               is int
-
-               // ip is used below to specify the real or complex eigenvalue:
-               //  ip == 0, real eigenvalue,
-               //        1, first  of conjugate complex pair (wr,wi),
-               //       -1, second of conjugate complex pair (wr,wi).
-               ip        int
-               iscomplex [nbmax]int // Stores ip for each column in current block.
-       )
-
-       if side == lapack.LeftEV {
-               goto leftev
-       }
-
-       // Compute right eigenvectors.
-
-       // For complex right vector, iv-1 is for real part and iv for complex
-       // part. Non-blocked version always uses iv=1, blocked version starts
-       // with iv=nb-1 and goes down to 0 or 1.
-       iv = max(2, nb) - 1
-       ip = 0
-       is = m - 1
-       for ki := n - 1; ki >= 0; ki-- {
-               if ip == -1 {
-                       // Previous iteration (ki+1) was second of
-                       // conjugate pair, so this ki is first of
-                       // conjugate pair.
-                       ip = 1
-                       continue
-               }
-
-               if ki == 0 || t[ki*ldt+ki-1] == 0 {
-                       // Last column or zero on sub-diagonal, so this
-                       // ki must be real eigenvalue.
-                       ip = 0
-               } else {
-                       // Non-zero on sub-diagonal, so this ki is
-                       // second of conjugate pair.
-                       ip = -1
-               }
-
-               if howmny == lapack.SelectedEV {
-                       if ip == 0 {
-                               if !selected[ki] {
-                                       continue
-                               }
-                       } else if !selected[ki-1] {
-                               continue
-                       }
-               }
-
-               // Compute the ki-th eigenvalue (wr,wi).
-               wr := t[ki*ldt+ki]
-               var wi float64
-               if ip != 0 {
-                       wi = math.Sqrt(math.Abs(t[ki*ldt+ki-1])) * math.Sqrt(math.Abs(t[(ki-1)*ldt+ki]))
-               }
-               smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum)
-
-               if ip == 0 {
-                       // Real right eigenvector.
-
-                       b[ki*ldb+iv] = 1
-                       // Form right-hand side.
-                       for k := 0; k < ki; k++ {
-                               b[k*ldb+iv] = -t[k*ldt+ki]
-                       }
-                       // Solve upper quasi-triangular system:
-                       //  [ T[0:ki,0:ki] - wr ]*X = scale*b.
-                       for j := ki - 1; j >= 0; {
-                               if j == 0 || t[j*ldt+j-1] == 0 {
-                                       // 1×1 diagonal block.
-                                       scale, xnorm, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt,
-                                               1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2)
-                                       // Scale X[0,0] to avoid overflow when updating the
-                                       // right-hand side.
-                                       if xnorm > 1 && norms[j] > bignum/xnorm {
-                                               x[0] /= xnorm
-                                               scale /= xnorm
-                                       }
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(ki+1, scale, b[iv:], ldb)
-                                       }
-                                       b[j*ldb+iv] = x[0]
-                                       // Update right-hand side.
-                                       bi.Daxpy(j, -x[0], t[j:], ldt, b[iv:], ldb)
-                                       j--
-                               } else {
-                                       // 2×2 diagonal block.
-                                       scale, xnorm, _ := impl.Dlaln2(false, 2, 1, smin, 1, t[(j-1)*ldt+j-1:], ldt,
-                                               1, 1, b[(j-1)*ldb+iv:], ldb, wr, 0, x[:3], 2)
-                                       // Scale X[0,0] and X[1,0] to avoid overflow
-                                       // when updating the right-hand side.
-                                       if xnorm > 1 {
-                                               beta := math.Max(norms[j-1], norms[j])
-                                               if beta > bignum/xnorm {
-                                                       x[0] /= xnorm
-                                                       x[2] /= xnorm
-                                                       scale /= xnorm
-                                               }
-                                       }
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(ki+1, scale, b[iv:], ldb)
-                                       }
-                                       b[(j-1)*ldb+iv] = x[0]
-                                       b[j*ldb+iv] = x[2]
-                                       // Update right-hand side.
-                                       bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv:], ldb)
-                                       bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv:], ldb)
-                                       j -= 2
-                               }
-                       }
-                       // Copy the vector x or Q*x to VR and normalize.
-                       switch {
-                       case howmny != lapack.AllEVMulQ:
-                               // No back-transform: copy x to VR and normalize.
-                               bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr)
-                               ii := bi.Idamax(ki+1, vr[is:], ldvr)
-                               remax := 1 / math.Abs(vr[ii*ldvr+is])
-                               bi.Dscal(ki+1, remax, vr[is:], ldvr)
-                               for k := ki + 1; k < n; k++ {
-                                       vr[k*ldvr+is] = 0
-                               }
-                       case nb == 1:
-                               // Version 1: back-transform each vector with GEMV, Q*x.
-                               if ki > 0 {
-                                       bi.Dgemv(blas.NoTrans, n, ki, 1, vr, ldvr, b[iv:], ldb,
-                                               b[ki*ldb+iv], vr[ki:], ldvr)
-                               }
-                               ii := bi.Idamax(n, vr[ki:], ldvr)
-                               remax := 1 / math.Abs(vr[ii*ldvr+ki])
-                               bi.Dscal(n, remax, vr[ki:], ldvr)
-                       default:
-                               // Version 2: back-transform block of vectors with GEMM.
-                               // Zero out below vector.
-                               for k := ki + 1; k < n; k++ {
-                                       b[k*ldb+iv] = 0
-                               }
-                               iscomplex[iv] = ip
-                               // Back-transform and normalization is done below.
-                       }
-               } else {
-                       // Complex right eigenvector.
-
-                       // Initial solve
-                       //  [ ( T[ki-1,ki-1] T[ki-1,ki] ) - (wr + i*wi) ]*X = 0.
-                       //  [ ( T[ki,  ki-1] T[ki,  ki] )               ]
-                       if math.Abs(t[(ki-1)*ldt+ki]) >= math.Abs(t[ki*ldt+ki-1]) {
-                               b[(ki-1)*ldb+iv-1] = 1
-                               b[ki*ldb+iv] = wi / t[(ki-1)*ldt+ki]
-                       } else {
-                               b[(ki-1)*ldb+iv-1] = -wi / t[ki*ldt+ki-1]
-                               b[ki*ldb+iv] = 1
-                       }
-                       b[ki*ldb+iv-1] = 0
-                       b[(ki-1)*ldb+iv] = 0
-                       // Form right-hand side.
-                       for k := 0; k < ki-1; k++ {
-                               b[k*ldb+iv-1] = -b[(ki-1)*ldb+iv-1] * t[k*ldt+ki-1]
-                               b[k*ldb+iv] = -b[ki*ldb+iv] * t[k*ldt+ki]
-                       }
-                       // Solve upper quasi-triangular system:
-                       //  [ T[0:ki-1,0:ki-1] - (wr+i*wi) ]*X = scale*(b1+i*b2)
-                       for j := ki - 2; j >= 0; {
-                               if j == 0 || t[j*ldt+j-1] == 0 {
-                                       // 1×1 diagonal block.
-
-                                       scale, xnorm, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt,
-                                               1, 1, b[j*ldb+iv-1:], ldb, wr, wi, x[:2], 2)
-                                       // Scale X[0,0] and X[0,1] to avoid
-                                       // overflow when updating the right-hand side.
-                                       if xnorm > 1 && norms[j] > bignum/xnorm {
-                                               x[0] /= xnorm
-                                               x[1] /= xnorm
-                                               scale /= xnorm
-                                       }
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(ki+1, scale, b[iv-1:], ldb)
-                                               bi.Dscal(ki+1, scale, b[iv:], ldb)
-                                       }
-                                       b[j*ldb+iv-1] = x[0]
-                                       b[j*ldb+iv] = x[1]
-                                       // Update the right-hand side.
-                                       bi.Daxpy(j, -x[0], t[j:], ldt, b[iv-1:], ldb)
-                                       bi.Daxpy(j, -x[1], t[j:], ldt, b[iv:], ldb)
-                                       j--
-                               } else {
-                                       // 2×2 diagonal block.
-
-                                       scale, xnorm, _ := impl.Dlaln2(false, 2, 2, smin, 1, t[(j-1)*ldt+j-1:], ldt,
-                                               1, 1, b[(j-1)*ldb+iv-1:], ldb, wr, wi, x[:], 2)
-                                       // Scale X to avoid overflow when updating
-                                       // the right-hand side.
-                                       if xnorm > 1 {
-                                               beta := math.Max(norms[j-1], norms[j])
-                                               if beta > bignum/xnorm {
-                                                       rec := 1 / xnorm
-                                                       x[0] *= rec
-                                                       x[1] *= rec
-                                                       x[2] *= rec
-                                                       x[3] *= rec
-                                                       scale *= rec
-                                               }
-                                       }
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(ki+1, scale, b[iv-1:], ldb)
-                                               bi.Dscal(ki+1, scale, b[iv:], ldb)
-                                       }
-                                       b[(j-1)*ldb+iv-1] = x[0]
-                                       b[(j-1)*ldb+iv] = x[1]
-                                       b[j*ldb+iv-1] = x[2]
-                                       b[j*ldb+iv] = x[3]
-                                       // Update the right-hand side.
-                                       bi.Daxpy(j-1, -x[0], t[j-1:], ldt, b[iv-1:], ldb)
-                                       bi.Daxpy(j-1, -x[1], t[j-1:], ldt, b[iv:], ldb)
-                                       bi.Daxpy(j-1, -x[2], t[j:], ldt, b[iv-1:], ldb)
-                                       bi.Daxpy(j-1, -x[3], t[j:], ldt, b[iv:], ldb)
-                                       j -= 2
-                               }
-                       }
-
-                       // Copy the vector x or Q*x to VR and normalize.
-                       switch {
-                       case howmny != lapack.AllEVMulQ:
-                               // No back-transform: copy x to VR and normalize.
-                               bi.Dcopy(ki+1, b[iv-1:], ldb, vr[is-1:], ldvr)
-                               bi.Dcopy(ki+1, b[iv:], ldb, vr[is:], ldvr)
-                               emax := 0.0
-                               for k := 0; k <= ki; k++ {
-                                       emax = math.Max(emax, math.Abs(vr[k*ldvr+is-1])+math.Abs(vr[k*ldvr+is]))
-                               }
-                               remax := 1 / emax
-                               bi.Dscal(ki+1, remax, vr[is-1:], ldvr)
-                               bi.Dscal(ki+1, remax, vr[is:], ldvr)
-                               for k := ki + 1; k < n; k++ {
-                                       vr[k*ldvr+is-1] = 0
-                                       vr[k*ldvr+is] = 0
-                               }
-                       case nb == 1:
-                               // Version 1: back-transform each vector with GEMV, Q*x.
-                               if ki-1 > 0 {
-                                       bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv-1:], ldb,
-                                               b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr)
-                                       bi.Dgemv(blas.NoTrans, n, ki-1, 1, vr, ldvr, b[iv:], ldb,
-                                               b[ki*ldb+iv], vr[ki:], ldvr)
-                               } else {
-                                       bi.Dscal(n, b[(ki-1)*ldb+iv-1], vr[ki-1:], ldvr)
-                                       bi.Dscal(n, b[ki*ldb+iv], vr[ki:], ldvr)
-                               }
-                               emax := 0.0
-                               for k := 0; k < n; k++ {
-                                       emax = math.Max(emax, math.Abs(vr[k*ldvr+ki-1])+math.Abs(vr[k*ldvr+ki]))
-                               }
-                               remax := 1 / emax
-                               bi.Dscal(n, remax, vr[ki-1:], ldvr)
-                               bi.Dscal(n, remax, vr[ki:], ldvr)
-                       default:
-                               // Version 2: back-transform block of vectors with GEMM.
-                               // Zero out below vector.
-                               for k := ki + 1; k < n; k++ {
-                                       b[k*ldb+iv-1] = 0
-                                       b[k*ldb+iv] = 0
-                               }
-                               iscomplex[iv-1] = -ip
-                               iscomplex[iv] = ip
-                               iv--
-                               // Back-transform and normalization is done below.
-                       }
-               }
-               if nb > 1 {
-                       // Blocked version of back-transform.
-
-                       // For complex case, ki2 includes both vectors (ki-1 and ki).
-                       ki2 := ki
-                       if ip != 0 {
-                               ki2--
-                       }
-                       // Columns iv:nb of b are valid vectors.
-                       // When the number of vectors stored reaches nb-1 or nb,
-                       // or if this was last vector, do the Gemm.
-                       if iv < 2 || ki2 == 0 {
-                               bi.Dgemm(blas.NoTrans, blas.NoTrans, n, nb-iv, ki2+nb-iv,
-                                       1, vr, ldvr, b[iv:], ldb,
-                                       0, b[nb+iv:], ldb)
-                               // Normalize vectors.
-                               var remax float64
-                               for k := iv; k < nb; k++ {
-                                       if iscomplex[k] == 0 {
-                                               // Real eigenvector.
-                                               ii := bi.Idamax(n, b[nb+k:], ldb)
-                                               remax = 1 / math.Abs(b[ii*ldb+nb+k])
-                                       } else if iscomplex[k] == 1 {
-                                               // First eigenvector of conjugate pair.
-                                               emax := 0.0
-                                               for ii := 0; ii < n; ii++ {
-                                                       emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1]))
-                                               }
-                                               remax = 1 / emax
-                                               // Second eigenvector of conjugate pair
-                                               // will reuse this value of remax.
-                                       }
-                                       bi.Dscal(n, remax, b[nb+k:], ldb)
-                               }
-                               impl.Dlacpy(blas.All, n, nb-iv, b[nb+iv:], ldb, vr[ki2:], ldvr)
-                               iv = nb - 1
-                       } else {
-                               iv--
-                       }
-               }
-               is--
-               if ip != 0 {
-                       is--
-               }
-       }
-
-       if side == lapack.RightEV {
-               return m
-       }
-
-leftev:
-       // Compute left eigenvectors.
-
-       // For complex left vector, iv is for real part and iv+1 for complex
-       // part. Non-blocked version always uses iv=0. Blocked version starts
-       // with iv=0, goes up to nb-2 or nb-1.
-       iv = 0
-       ip = 0
-       is = 0
-       for ki := 0; ki < n; ki++ {
-               if ip == 1 {
-                       // Previous iteration ki-1 was first of conjugate pair,
-                       // so this ki is second of conjugate pair.
-                       ip = -1
-                       continue
-               }
-
-               if ki == n-1 || t[(ki+1)*ldt+ki] == 0 {
-                       // Last column or zero on sub-diagonal, so this ki must
-                       // be real eigenvalue.
-                       ip = 0
-               } else {
-                       // Non-zero on sub-diagonal, so this ki is first of
-                       // conjugate pair.
-                       ip = 1
-               }
-               if howmny == lapack.SelectedEV && !selected[ki] {
-                       continue
-               }
-
-               // Compute the ki-th eigenvalue (wr,wi).
-               wr := t[ki*ldt+ki]
-               var wi float64
-               if ip != 0 {
-                       wi = math.Sqrt(math.Abs(t[ki*ldt+ki+1])) * math.Sqrt(math.Abs(t[(ki+1)*ldt+ki]))
-               }
-               smin := math.Max(ulp*(math.Abs(wr)+math.Abs(wi)), smlnum)
-
-               if ip == 0 {
-                       // Real left eigenvector.
-
-                       b[ki*ldb+iv] = 1
-                       // Form right-hand side.
-                       for k := ki + 1; k < n; k++ {
-                               b[k*ldb+iv] = -t[ki*ldt+k]
-                       }
-                       // Solve transposed quasi-triangular system:
-                       //  [ T[ki+1:n,ki+1:n] - wr ]^T * X = scale*b
-                       vmax := 1.0
-                       vcrit := bignum
-                       for j := ki + 1; j < n; {
-                               if j == n-1 || t[(j+1)*ldt+j] == 0 {
-                                       // 1×1 diagonal block.
-
-                                       // Scale if necessary to avoid overflow
-                                       // when forming the right-hand side.
-                                       if norms[j] > vcrit {
-                                               rec := 1 / vmax
-                                               bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb)
-                                               vmax = 1
-                                               vcrit = bignum
-                                       }
-                                       b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb)
-                                       // Solve [ T[j,j] - wr ]^T * X = b.
-                                       scale, _, _ := impl.Dlaln2(false, 1, 1, smin, 1, t[j*ldt+j:], ldt,
-                                               1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:1], 2)
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb)
-                                       }
-                                       b[j*ldb+iv] = x[0]
-                                       vmax = math.Max(math.Abs(b[j*ldb+iv]), vmax)
-                                       vcrit = bignum / vmax
-                                       j++
-                               } else {
-                                       // 2×2 diagonal block.
-
-                                       // Scale if necessary to avoid overflow
-                                       // when forming the right-hand side.
-                                       beta := math.Max(norms[j], norms[j+1])
-                                       if beta > vcrit {
-                                               bi.Dscal(n-ki+1, 1/vmax, b[ki*ldb+iv:], 1)
-                                               vmax = 1
-                                               vcrit = bignum
-                                       }
-                                       b[j*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j:], ldt, b[(ki+1)*ldb+iv:], ldb)
-                                       b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-1, t[(ki+1)*ldt+j+1:], ldt, b[(ki+1)*ldb+iv:], ldb)
-                                       // Solve
-                                       //  [ T[j,j]-wr  T[j,j+1]      ]^T * X = scale*[ b1 ]
-                                       //  [ T[j+1,j]   T[j+1,j+1]-wr ]               [ b2 ]
-                                       scale, _, _ := impl.Dlaln2(true, 2, 1, smin, 1, t[j*ldt+j:], ldt,
-                                               1, 1, b[j*ldb+iv:], ldb, wr, 0, x[:3], 2)
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb)
-                                       }
-                                       b[j*ldb+iv] = x[0]
-                                       b[(j+1)*ldb+iv] = x[2]
-                                       vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[(j+1)*ldb+iv])))
-                                       vcrit = bignum / vmax
-                                       j += 2
-                               }
-                       }
-                       // Copy the vector x or Q*x to VL and normalize.
-                       switch {
-                       case howmny != lapack.AllEVMulQ:
-                               // No back-transform: copy x to VL and normalize.
-                               bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl)
-                               ii := bi.Idamax(n-ki, vl[ki*ldvl+is:], ldvl) + ki
-                               remax := 1 / math.Abs(vl[ii*ldvl+is])
-                               bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl)
-                               for k := 0; k < ki; k++ {
-                                       vl[k*ldvl+is] = 0
-                               }
-                       case nb == 1:
-                               // Version 1: back-transform each vector with Gemv, Q*x.
-                               if n-ki-1 > 0 {
-                                       bi.Dgemv(blas.NoTrans, n, n-ki-1,
-                                               1, vl[ki+1:], ldvl, b[(ki+1)*ldb+iv:], ldb,
-                                               b[ki*ldb+iv], vl[ki:], ldvl)
-                               }
-                               ii := bi.Idamax(n, vl[ki:], ldvl)
-                               remax := 1 / math.Abs(vl[ii*ldvl+ki])
-                               bi.Dscal(n, remax, vl[ki:], ldvl)
-                       default:
-                               // Version 2: back-transform block of vectors with Gemm
-                               // zero out above vector.
-                               for k := 0; k < ki; k++ {
-                                       b[k*ldb+iv] = 0
-                               }
-                               iscomplex[iv] = ip
-                               // Back-transform and normalization is done below.
-                       }
-               } else {
-                       // Complex left eigenvector.
-
-                       // Initial solve:
-                       // [ [ T[ki,ki]   T[ki,ki+1]   ]^T - (wr - i* wi) ]*X = 0.
-                       // [ [ T[ki+1,ki] T[ki+1,ki+1] ]                  ]
-                       if math.Abs(t[ki*ldt+ki+1]) >= math.Abs(t[(ki+1)*ldt+ki]) {
-                               b[ki*ldb+iv] = wi / t[ki*ldt+ki+1]
-                               b[(ki+1)*ldb+iv+1] = 1
-                       } else {
-                               b[ki*ldb+iv] = 1
-                               b[(ki+1)*ldb+iv+1] = -wi / t[(ki+1)*ldt+ki]
-                       }
-                       b[(ki+1)*ldb+iv] = 0
-                       b[ki*ldb+iv+1] = 0
-                       // Form right-hand side.
-                       for k := ki + 2; k < n; k++ {
-                               b[k*ldb+iv] = -b[ki*ldb+iv] * t[ki*ldt+k]
-                               b[k*ldb+iv+1] = -b[(ki+1)*ldb+iv+1] * t[(ki+1)*ldt+k]
-                       }
-                       // Solve transposed quasi-triangular system:
-                       // [ T[ki+2:n,ki+2:n]^T - (wr-i*wi) ]*X = b1+i*b2
-                       vmax := 1.0
-                       vcrit := bignum
-                       for j := ki + 2; j < n; {
-                               if j == n-1 || t[(j+1)*ldt+j] == 0 {
-                                       // 1×1 diagonal block.
-
-                                       // Scale if necessary to avoid overflow
-                                       // when forming the right-hand side elements.
-                                       if norms[j] > vcrit {
-                                               rec := 1 / vmax
-                                               bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb)
-                                               bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb)
-                                               vmax = 1
-                                               vcrit = bignum
-                                       }
-                                       b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb)
-                                       b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb)
-                                       // Solve [ T[j,j]-(wr-i*wi) ]*(X11+i*X12) = b1+i*b2.
-                                       scale, _, _ := impl.Dlaln2(false, 1, 2, smin, 1, t[j*ldt+j:], ldt,
-                                               1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:2], 2)
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb)
-                                               bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb)
-                                       }
-                                       b[j*ldb+iv] = x[0]
-                                       b[j*ldb+iv+1] = x[1]
-                                       vmax = math.Max(vmax, math.Max(math.Abs(b[j*ldb+iv]), math.Abs(b[j*ldb+iv+1])))
-                                       vcrit = bignum / vmax
-                                       j++
-                               } else {
-                                       // 2×2 diagonal block.
-
-                                       // Scale if necessary to avoid overflow
-                                       // when forming the right-hand side elements.
-                                       if math.Max(norms[j], norms[j+1]) > vcrit {
-                                               rec := 1 / vmax
-                                               bi.Dscal(n-ki, rec, b[ki*ldb+iv:], ldb)
-                                               bi.Dscal(n-ki, rec, b[ki*ldb+iv+1:], ldb)
-                                               vmax = 1
-                                               vcrit = bignum
-                                       }
-                                       b[j*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv:], ldb)
-                                       b[j*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j:], ldt, b[(ki+2)*ldb+iv+1:], ldb)
-                                       b[(j+1)*ldb+iv] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv:], ldb)
-                                       b[(j+1)*ldb+iv+1] -= bi.Ddot(j-ki-2, t[(ki+2)*ldt+j+1:], ldt, b[(ki+2)*ldb+iv+1:], ldb)
-                                       // Solve 2×2 complex linear equation
-                                       //  [ [T[j,j]   T[j,j+1]  ]^T - (wr-i*wi)*I ]*X = scale*b
-                                       //  [ [T[j+1,j] T[j+1,j+1]]                 ]
-                                       scale, _, _ := impl.Dlaln2(true, 2, 2, smin, 1, t[j*ldt+j:], ldt,
-                                               1, 1, b[j*ldb+iv:], ldb, wr, -wi, x[:], 2)
-                                       // Scale if necessary.
-                                       if scale != 1 {
-                                               bi.Dscal(n-ki, scale, b[ki*ldb+iv:], ldb)
-                                               bi.Dscal(n-ki, scale, b[ki*ldb+iv+1:], ldb)
-                                       }
-                                       b[j*ldb+iv] = x[0]
-                                       b[j*ldb+iv+1] = x[1]
-                                       b[(j+1)*ldb+iv] = x[2]
-                                       b[(j+1)*ldb+iv+1] = x[3]
-                                       vmax01 := math.Max(math.Abs(x[0]), math.Abs(x[1]))
-                                       vmax23 := math.Max(math.Abs(x[2]), math.Abs(x[3]))
-                                       vmax = math.Max(vmax, math.Max(vmax01, vmax23))
-                                       vcrit = bignum / vmax
-                                       j += 2
-                               }
-                       }
-                       // Copy the vector x or Q*x to VL and normalize.
-                       switch {
-                       case howmny != lapack.AllEVMulQ:
-                               // No back-transform: copy x to VL and normalize.
-                               bi.Dcopy(n-ki, b[ki*ldb+iv:], ldb, vl[ki*ldvl+is:], ldvl)
-                               bi.Dcopy(n-ki, b[ki*ldb+iv+1:], ldb, vl[ki*ldvl+is+1:], ldvl)
-                               emax := 0.0
-                               for k := ki; k < n; k++ {
-                                       emax = math.Max(emax, math.Abs(vl[k*ldvl+is])+math.Abs(vl[k*ldvl+is+1]))
-                               }
-                               remax := 1 / emax
-                               bi.Dscal(n-ki, remax, vl[ki*ldvl+is:], ldvl)
-                               bi.Dscal(n-ki, remax, vl[ki*ldvl+is+1:], ldvl)
-                               for k := 0; k < ki; k++ {
-                                       vl[k*ldvl+is] = 0
-                                       vl[k*ldvl+is+1] = 0
-                               }
-                       case nb == 1:
-                               // Version 1: back-transform each vector with GEMV, Q*x.
-                               if n-ki-2 > 0 {
-                                       bi.Dgemv(blas.NoTrans, n, n-ki-2,
-                                               1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv:], ldb,
-                                               b[ki*ldb+iv], vl[ki:], ldvl)
-                                       bi.Dgemv(blas.NoTrans, n, n-ki-2,
-                                               1, vl[ki+2:], ldvl, b[(ki+2)*ldb+iv+1:], ldb,
-                                               b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl)
-                               } else {
-                                       bi.Dscal(n, b[ki*ldb+iv], vl[ki:], ldvl)
-                                       bi.Dscal(n, b[(ki+1)*ldb+iv+1], vl[ki+1:], ldvl)
-                               }
-                               emax := 0.0
-                               for k := 0; k < n; k++ {
-                                       emax = math.Max(emax, math.Abs(vl[k*ldvl+ki])+math.Abs(vl[k*ldvl+ki+1]))
-                               }
-                               remax := 1 / emax
-                               bi.Dscal(n, remax, vl[ki:], ldvl)
-                               bi.Dscal(n, remax, vl[ki+1:], ldvl)
-                       default:
-                               // Version 2: back-transform block of vectors with GEMM.
-                               // Zero out above vector.
-                               // Could go from ki-nv+1 to ki-1.
-                               for k := 0; k < ki; k++ {
-                                       b[k*ldb+iv] = 0
-                                       b[k*ldb+iv+1] = 0
-                               }
-                               iscomplex[iv] = ip
-                               iscomplex[iv+1] = -ip
-                               iv++
-                               // Back-transform and normalization is done below.
-                       }
-               }
-               if nb > 1 {
-                       // Blocked version of back-transform.
-                       // For complex case, ki2 includes both vectors ki and ki+1.
-                       ki2 := ki
-                       if ip != 0 {
-                               ki2++
-                       }
-                       // Columns [0:iv] of work are valid vectors. When the
-                       // number of vectors stored reaches nb-1 or nb, or if
-                       // this was last vector, do the Gemm.
-                       if iv >= nb-2 || ki2 == n-1 {
-                               bi.Dgemm(blas.NoTrans, blas.NoTrans, n, iv+1, n-ki2+iv,
-                                       1, vl[ki2-iv:], ldvl, b[(ki2-iv)*ldb:], ldb,
-                                       0, b[nb:], ldb)
-                               // Normalize vectors.
-                               var remax float64
-                               for k := 0; k <= iv; k++ {
-                                       if iscomplex[k] == 0 {
-                                               // Real eigenvector.
-                                               ii := bi.Idamax(n, b[nb+k:], ldb)
-                                               remax = 1 / math.Abs(b[ii*ldb+nb+k])
-                                       } else if iscomplex[k] == 1 {
-                                               // First eigenvector of conjugate pair.
-                                               emax := 0.0
-                                               for ii := 0; ii < n; ii++ {
-                                                       emax = math.Max(emax, math.Abs(b[ii*ldb+nb+k])+math.Abs(b[ii*ldb+nb+k+1]))
-                                               }
-                                               remax = 1 / emax
-                                               // Second eigenvector of conjugate pair
-                                               // will reuse this value of remax.
-                                       }
-                                       bi.Dscal(n, remax, b[nb+k:], ldb)
-                               }
-                               impl.Dlacpy(blas.All, n, iv+1, b[nb:], ldb, vl[ki2-iv:], ldvl)
-                               iv = 0
-                       } else {
-                               iv++
-                       }
-               }
-               is++
-               if ip != 0 {
-                       is++
-               }
-       }
-
-       return m
-}