github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/lapack/lapack64/lapack64.go (about)

     1  // Copyright ©2015 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package lapack64
     6  
     7  import (
     8  	"github.com/jingcheng-WU/gonum/blas"
     9  	"github.com/jingcheng-WU/gonum/blas/blas64"
    10  	"github.com/jingcheng-WU/gonum/lapack"
    11  	"github.com/jingcheng-WU/gonum/lapack/gonum"
    12  )
    13  
    14  var lapack64 lapack.Float64 = gonum.Implementation{}
    15  
    16  // Use sets the LAPACK float64 implementation to be used by subsequent BLAS calls.
    17  // The default implementation is native.Implementation.
    18  func Use(l lapack.Float64) {
    19  	lapack64 = l
    20  }
    21  
    22  // Tridiagonal represents a tridiagonal matrix using its three diagonals.
    23  type Tridiagonal struct {
    24  	N  int
    25  	DL []float64
    26  	D  []float64
    27  	DU []float64
    28  }
    29  
    30  func max(a, b int) int {
    31  	if a > b {
    32  		return a
    33  	}
    34  	return b
    35  }
    36  
    37  // Potrf computes the Cholesky factorization of a.
    38  // The factorization has the form
    39  //  A = Uᵀ * U  if a.Uplo == blas.Upper, or
    40  //  A = L * Lᵀ  if a.Uplo == blas.Lower,
    41  // where U is an upper triangular matrix and L is lower triangular.
    42  // The triangular matrix is returned in t, and the underlying data between
    43  // a and t is shared. The returned bool indicates whether a is positive
    44  // definite and the factorization could be finished.
    45  func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) {
    46  	ok = lapack64.Dpotrf(a.Uplo, a.N, a.Data, max(1, a.Stride))
    47  	t.Uplo = a.Uplo
    48  	t.N = a.N
    49  	t.Data = a.Data
    50  	t.Stride = a.Stride
    51  	t.Diag = blas.NonUnit
    52  	return
    53  }
    54  
    55  // Potri computes the inverse of a real symmetric positive definite matrix A
    56  // using its Cholesky factorization.
    57  //
    58  // On entry, t contains the triangular factor U or L from the Cholesky
    59  // factorization A = Uᵀ*U or A = L*Lᵀ, as computed by Potrf.
    60  //
    61  // On return, the upper or lower triangle of the (symmetric) inverse of A is
    62  // stored in t, overwriting the input factor U or L, and also returned in a. The
    63  // underlying data between a and t is shared.
    64  //
    65  // The returned bool indicates whether the inverse was computed successfully.
    66  func Potri(t blas64.Triangular) (a blas64.Symmetric, ok bool) {
    67  	ok = lapack64.Dpotri(t.Uplo, t.N, t.Data, max(1, t.Stride))
    68  	a.Uplo = t.Uplo
    69  	a.N = t.N
    70  	a.Data = t.Data
    71  	a.Stride = t.Stride
    72  	return
    73  }
    74  
    75  // Potrs solves a system of n linear equations A*X = B where A is an n×n
    76  // symmetric positive definite matrix and B is an n×nrhs matrix, using the
    77  // Cholesky factorization A = Uᵀ*U or A = L*Lᵀ. t contains the corresponding
    78  // triangular factor as returned by Potrf. On entry, B contains the right-hand
    79  // side matrix B, on return it contains the solution matrix X.
    80  func Potrs(t blas64.Triangular, b blas64.General) {
    81  	lapack64.Dpotrs(t.Uplo, t.N, b.Cols, t.Data, max(1, t.Stride), b.Data, max(1, b.Stride))
    82  }
    83  
    84  // Pbcon returns an estimate of the reciprocal of the condition number (in the
    85  // 1-norm) of an n×n symmetric positive definite band matrix using the Cholesky
    86  // factorization
    87  //  A = Uᵀ*U  if uplo == blas.Upper
    88  //  A = L*Lᵀ  if uplo == blas.Lower
    89  // computed by Pbtrf. The estimate is obtained for norm(inv(A)), and the
    90  // reciprocal of the condition number is computed as
    91  //  rcond = 1 / (anorm * norm(inv(A))).
    92  //
    93  // The length of work must be at least 3*n and the length of iwork must be at
    94  // least n.
    95  func Pbcon(a blas64.SymmetricBand, anorm float64, work []float64, iwork []int) float64 {
    96  	return lapack64.Dpbcon(a.Uplo, a.N, a.K, a.Data, a.Stride, anorm, work, iwork)
    97  }
    98  
    99  // Pbtrf computes the Cholesky factorization of an n×n symmetric positive
   100  // definite band matrix
   101  //  A = Uᵀ * U  if a.Uplo == blas.Upper
   102  //  A = L * Lᵀ  if a.Uplo == blas.Lower
   103  // where U and L are upper, respectively lower, triangular band matrices.
   104  //
   105  // The triangular matrix U or L is returned in t, and the underlying data
   106  // between a and t is shared. The returned bool indicates whether A is positive
   107  // definite and the factorization could be finished.
   108  func Pbtrf(a blas64.SymmetricBand) (t blas64.TriangularBand, ok bool) {
   109  	ok = lapack64.Dpbtrf(a.Uplo, a.N, a.K, a.Data, max(1, a.Stride))
   110  	t.Uplo = a.Uplo
   111  	t.Diag = blas.NonUnit
   112  	t.N = a.N
   113  	t.K = a.K
   114  	t.Data = a.Data
   115  	t.Stride = a.Stride
   116  	return t, ok
   117  }
   118  
   119  // Pbtrs solves a system of linear equations A*X = B with an n×n symmetric
   120  // positive definite band matrix A using the Cholesky factorization
   121  //  A = Uᵀ * U  if t.Uplo == blas.Upper
   122  //  A = L * Lᵀ  if t.Uplo == blas.Lower
   123  // t contains the corresponding triangular factor as returned by Pbtrf.
   124  //
   125  // On entry, b contains the right hand side matrix B. On return, it is
   126  // overwritten with the solution matrix X.
   127  func Pbtrs(t blas64.TriangularBand, b blas64.General) {
   128  	lapack64.Dpbtrs(t.Uplo, t.N, t.K, b.Cols, t.Data, max(1, t.Stride), b.Data, max(1, b.Stride))
   129  }
   130  
   131  // Gecon estimates the reciprocal of the condition number of the n×n matrix A
   132  // given the LU decomposition of the matrix. The condition number computed may
   133  // be based on the 1-norm or the ∞-norm.
   134  //
   135  // a contains the result of the LU decomposition of A as computed by Getrf.
   136  //
   137  // anorm is the corresponding 1-norm or ∞-norm of the original matrix A.
   138  //
   139  // work is a temporary data slice of length at least 4*n and Gecon will panic otherwise.
   140  //
   141  // iwork is a temporary data slice of length at least n and Gecon will panic otherwise.
   142  func Gecon(norm lapack.MatrixNorm, a blas64.General, anorm float64, work []float64, iwork []int) float64 {
   143  	return lapack64.Dgecon(norm, a.Cols, a.Data, max(1, a.Stride), anorm, work, iwork)
   144  }
   145  
   146  // Gels finds a minimum-norm solution based on the matrices A and B using the
   147  // QR or LQ factorization. Gels returns false if the matrix
   148  // A is singular, and true if this solution was successfully found.
   149  //
   150  // The minimization problem solved depends on the input parameters.
   151  //
   152  //  1. If m >= n and trans == blas.NoTrans, Gels finds X such that || A*X - B||_2
   153  //     is minimized.
   154  //  2. If m < n and trans == blas.NoTrans, Gels finds the minimum norm solution of
   155  //     A * X = B.
   156  //  3. If m >= n and trans == blas.Trans, Gels finds the minimum norm solution of
   157  //     Aᵀ * X = B.
   158  //  4. If m < n and trans == blas.Trans, Gels finds X such that || A*X - B||_2
   159  //     is minimized.
   160  // Note that the least-squares solutions (cases 1 and 3) perform the minimization
   161  // per column of B. This is not the same as finding the minimum-norm matrix.
   162  //
   163  // The matrix A is a general matrix of size m×n and is modified during this call.
   164  // The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry,
   165  // the elements of b specify the input matrix B. B has size m×nrhs if
   166  // trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the
   167  // leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans,
   168  // this submatrix is of size n×nrhs, and of size m×nrhs otherwise.
   169  //
   170  // Work is temporary storage, and lwork specifies the usable memory length.
   171  // At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic
   172  // otherwise. A longer work will enable blocked algorithms to be called.
   173  // In the special case that lwork == -1, work[0] will be set to the optimal working
   174  // length.
   175  func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float64, lwork int) bool {
   176  	return lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride), work, lwork)
   177  }
   178  
   179  // Geqrf computes the QR factorization of the m×n matrix A using a blocked
   180  // algorithm. A is modified to contain the information to construct Q and R.
   181  // The upper triangle of a contains the matrix R. The lower triangular elements
   182  // (not including the diagonal) contain the elementary reflectors. tau is modified
   183  // to contain the reflector scales. tau must have length at least min(m,n), and
   184  // this function will panic otherwise.
   185  //
   186  // The ith elementary reflector can be explicitly constructed by first extracting
   187  // the
   188  //  v[j] = 0           j < i
   189  //  v[j] = 1           j == i
   190  //  v[j] = a[j*lda+i]  j > i
   191  // and computing H_i = I - tau[i] * v * vᵀ.
   192  //
   193  // The orthonormal matrix Q can be constucted from a product of these elementary
   194  // reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n).
   195  //
   196  // Work is temporary storage, and lwork specifies the usable memory length.
   197  // At minimum, lwork >= m and this function will panic otherwise.
   198  // Geqrf is a blocked QR factorization, but the block size is limited
   199  // by the temporary space available. If lwork == -1, instead of performing Geqrf,
   200  // the optimal work length will be stored into work[0].
   201  func Geqrf(a blas64.General, tau, work []float64, lwork int) {
   202  	lapack64.Dgeqrf(a.Rows, a.Cols, a.Data, max(1, a.Stride), tau, work, lwork)
   203  }
   204  
   205  // Gelqf computes the LQ factorization of the m×n matrix A using a blocked
   206  // algorithm. A is modified to contain the information to construct L and Q. The
   207  // lower triangle of a contains the matrix L. The elements above the diagonal
   208  // and the slice tau represent the matrix Q. tau is modified to contain the
   209  // reflector scales. tau must have length at least min(m,n), and this function
   210  // will panic otherwise.
   211  //
   212  // See Geqrf for a description of the elementary reflectors and orthonormal
   213  // matrix Q. Q is constructed as a product of these elementary reflectors,
   214  // Q = H_{k-1} * ... * H_1 * H_0.
   215  //
   216  // Work is temporary storage, and lwork specifies the usable memory length.
   217  // At minimum, lwork >= m and this function will panic otherwise.
   218  // Gelqf is a blocked LQ factorization, but the block size is limited
   219  // by the temporary space available. If lwork == -1, instead of performing Gelqf,
   220  // the optimal work length will be stored into work[0].
   221  func Gelqf(a blas64.General, tau, work []float64, lwork int) {
   222  	lapack64.Dgelqf(a.Rows, a.Cols, a.Data, max(1, a.Stride), tau, work, lwork)
   223  }
   224  
   225  // Gesvd computes the singular value decomposition of the input matrix A.
   226  //
   227  // The singular value decomposition is
   228  //  A = U * Sigma * Vᵀ
   229  // where Sigma is an m×n diagonal matrix containing the singular values of A,
   230  // U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first
   231  // min(m,n) columns of U and V are the left and right singular vectors of A
   232  // respectively.
   233  //
   234  // jobU and jobVT are options for computing the singular vectors. The behavior
   235  // is as follows
   236  //  jobU == lapack.SVDAll       All m columns of U are returned in u
   237  //  jobU == lapack.SVDStore     The first min(m,n) columns are returned in u
   238  //  jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a
   239  //  jobU == lapack.SVDNone      The columns of U are not computed.
   240  // The behavior is the same for jobVT and the rows of Vᵀ. At most one of jobU
   241  // and jobVT can equal lapack.SVDOverwrite, and Gesvd will panic otherwise.
   242  //
   243  // On entry, a contains the data for the m×n matrix A. During the call to Gesvd
   244  // the data is overwritten. On exit, A contains the appropriate singular vectors
   245  // if either job is lapack.SVDOverwrite.
   246  //
   247  // s is a slice of length at least min(m,n) and on exit contains the singular
   248  // values in decreasing order.
   249  //
   250  // u contains the left singular vectors on exit, stored columnwise. If
   251  // jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDStore u is
   252  // of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is
   253  // not used.
   254  //
   255  // vt contains the left singular vectors on exit, stored rowwise. If
   256  // jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDStore vt is
   257  // of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is
   258  // not used.
   259  //
   260  // work is a slice for storing temporary memory, and lwork is the usable size of
   261  // the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)).
   262  // If lwork == -1, instead of performing Gesvd, the optimal work length will be
   263  // stored into work[0]. Gesvd will panic if the working memory has insufficient
   264  // storage.
   265  //
   266  // Gesvd returns whether the decomposition successfully completed.
   267  func Gesvd(jobU, jobVT lapack.SVDJob, a, u, vt blas64.General, s, work []float64, lwork int) (ok bool) {
   268  	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)
   269  }
   270  
   271  // Getrf computes the LU decomposition of the m×n matrix A.
   272  // The LU decomposition is a factorization of A into
   273  //  A = P * L * U
   274  // where P is a permutation matrix, L is a unit lower triangular matrix, and
   275  // U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored
   276  // in place into a.
   277  //
   278  // ipiv is a permutation vector. It indicates that row i of the matrix was
   279  // changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic
   280  // otherwise. ipiv is zero-indexed.
   281  //
   282  // Getrf is the blocked version of the algorithm.
   283  //
   284  // Getrf returns whether the matrix A is singular. The LU decomposition will
   285  // be computed regardless of the singularity of A, but division by zero
   286  // will occur if the false is returned and the result is used to solve a
   287  // system of equations.
   288  func Getrf(a blas64.General, ipiv []int) bool {
   289  	return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, max(1, a.Stride), ipiv)
   290  }
   291  
   292  // Getri computes the inverse of the matrix A using the LU factorization computed
   293  // by Getrf. On entry, a contains the PLU decomposition of A as computed by
   294  // Getrf and on exit contains the reciprocal of the original matrix.
   295  //
   296  // Getri will not perform the inversion if the matrix is singular, and returns
   297  // a boolean indicating whether the inversion was successful.
   298  //
   299  // Work is temporary storage, and lwork specifies the usable memory length.
   300  // At minimum, lwork >= n and this function will panic otherwise.
   301  // Getri is a blocked inversion, but the block size is limited
   302  // by the temporary space available. If lwork == -1, instead of performing Getri,
   303  // the optimal work length will be stored into work[0].
   304  func Getri(a blas64.General, ipiv []int, work []float64, lwork int) (ok bool) {
   305  	return lapack64.Dgetri(a.Cols, a.Data, max(1, a.Stride), ipiv, work, lwork)
   306  }
   307  
   308  // Getrs solves a system of equations using an LU factorization.
   309  // The system of equations solved is
   310  //  A * X = B   if trans == blas.Trans
   311  //  Aᵀ * X = B  if trans == blas.NoTrans
   312  // A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs.
   313  //
   314  // On entry b contains the elements of the matrix B. On exit, b contains the
   315  // elements of X, the solution to the system of equations.
   316  //
   317  // a and ipiv contain the LU factorization of A and the permutation indices as
   318  // computed by Getrf. ipiv is zero-indexed.
   319  func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) {
   320  	lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, max(1, a.Stride), ipiv, b.Data, max(1, b.Stride))
   321  }
   322  
   323  // Ggsvd3 computes the generalized singular value decomposition (GSVD)
   324  // of an m×n matrix A and p×n matrix B:
   325  //  Uᵀ*A*Q = D1*[ 0 R ]
   326  //
   327  //  Vᵀ*B*Q = D2*[ 0 R ]
   328  // where U, V and Q are orthogonal matrices.
   329  //
   330  // Ggsvd3 returns k and l, the dimensions of the sub-blocks. k+l
   331  // is the effective numerical rank of the (m+p)×n matrix [ Aᵀ Bᵀ ]ᵀ.
   332  // R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and
   333  // D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following
   334  // structures, respectively:
   335  //
   336  // If m-k-l >= 0,
   337  //
   338  //                    k  l
   339  //       D1 =     k [ I  0 ]
   340  //                l [ 0  C ]
   341  //            m-k-l [ 0  0 ]
   342  //
   343  //                  k  l
   344  //       D2 = l   [ 0  S ]
   345  //            p-l [ 0  0 ]
   346  //
   347  //               n-k-l  k    l
   348  //  [ 0 R ] = k [  0   R11  R12 ] k
   349  //            l [  0    0   R22 ] l
   350  //
   351  // where
   352  //
   353  //  C = diag( alpha_k, ... , alpha_{k+l} ),
   354  //  S = diag( beta_k,  ... , beta_{k+l} ),
   355  //  C^2 + S^2 = I.
   356  //
   357  // R is stored in
   358  //  A[0:k+l, n-k-l:n]
   359  // on exit.
   360  //
   361  // If m-k-l < 0,
   362  //
   363  //                 k m-k k+l-m
   364  //      D1 =   k [ I  0    0  ]
   365  //           m-k [ 0  C    0  ]
   366  //
   367  //                   k m-k k+l-m
   368  //      D2 =   m-k [ 0  S    0  ]
   369  //           k+l-m [ 0  0    I  ]
   370  //             p-l [ 0  0    0  ]
   371  //
   372  //                 n-k-l  k   m-k  k+l-m
   373  //  [ 0 R ] =    k [ 0    R11  R12  R13 ]
   374  //             m-k [ 0     0   R22  R23 ]
   375  //           k+l-m [ 0     0    0   R33 ]
   376  //
   377  // where
   378  //  C = diag( alpha_k, ... , alpha_m ),
   379  //  S = diag( beta_k,  ... , beta_m ),
   380  //  C^2 + S^2 = I.
   381  //
   382  //  R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n]
   383  //      [  0  R22 R23 ]
   384  // and R33 is stored in
   385  //  B[m-k:l, n+m-k-l:n] on exit.
   386  //
   387  // Ggsvd3 computes C, S, R, and optionally the orthogonal transformation
   388  // matrices U, V and Q.
   389  //
   390  // jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior
   391  // is as follows
   392  //  jobU == lapack.GSVDU        Compute orthogonal matrix U
   393  //  jobU == lapack.GSVDNone     Do not compute orthogonal matrix.
   394  // The behavior is the same for jobV and jobQ with the exception that instead of
   395  // lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively.
   396  // The matrices U, V and Q must be m×m, p×p and n×n respectively unless the
   397  // relevant job parameter is lapack.GSVDNone.
   398  //
   399  // alpha and beta must have length n or Ggsvd3 will panic. On exit, alpha and
   400  // beta contain the generalized singular value pairs of A and B
   401  //   alpha[0:k] = 1,
   402  //   beta[0:k]  = 0,
   403  // if m-k-l >= 0,
   404  //   alpha[k:k+l] = diag(C),
   405  //   beta[k:k+l]  = diag(S),
   406  // if m-k-l < 0,
   407  //   alpha[k:m]= C, alpha[m:k+l]= 0
   408  //   beta[k:m] = S, beta[m:k+l] = 1.
   409  // if k+l < n,
   410  //   alpha[k+l:n] = 0 and
   411  //   beta[k+l:n]  = 0.
   412  //
   413  // On exit, iwork contains the permutation required to sort alpha descending.
   414  //
   415  // iwork must have length n, work must have length at least max(1, lwork), and
   416  // lwork must be -1 or greater than n, otherwise Ggsvd3 will panic. If
   417  // lwork is -1, work[0] holds the optimal lwork on return, but Ggsvd3 does
   418  // not perform the GSVD.
   419  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) {
   420  	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)
   421  }
   422  
   423  // Gtsv solves one of the equations
   424  //  A * X = B   if trans == blas.NoTrans
   425  //  Aᵀ * X = B  if trans == blas.Trans or blas.ConjTrans
   426  // where A is an n×n tridiagonal matrix. It uses Gaussian elimination with
   427  // partial pivoting.
   428  //
   429  // On entry, a contains the matrix A, on return it will be overwritten.
   430  //
   431  // On entry, b contains the n×nrhs right-hand side matrix B. On return, it will
   432  // be overwritten. If ok is true, it will be overwritten by the solution matrix X.
   433  //
   434  // Gtsv returns whether the solution X has been successfuly computed.
   435  //
   436  // Dgtsv is not part of the lapack.Float64 interface and so calls to Gtsv are
   437  // always executed by the Gonum implementation.
   438  func Gtsv(trans blas.Transpose, a Tridiagonal, b blas64.General) (ok bool) {
   439  	if trans != blas.NoTrans {
   440  		a.DL, a.DU = a.DU, a.DL
   441  	}
   442  	return gonum.Implementation{}.Dgtsv(a.N, b.Cols, a.DL, a.D, a.DU, b.Data, max(1, b.Stride))
   443  }
   444  
   445  // Lagtm performs one of the matrix-matrix operations
   446  //  C = alpha * A * B + beta * C   if trans == blas.NoTrans
   447  //  C = alpha * Aᵀ * B + beta * C  if trans == blas.Trans or blas.ConjTrans
   448  // where A is an m×m tridiagonal matrix represented by its diagonals dl, d, du,
   449  // B and C are m×n dense matrices, and alpha and beta are scalars.
   450  //
   451  // Dlagtm is not part of the lapack.Float64 interface and so calls to Lagtm are
   452  // always executed by the Gonum implementation.
   453  func Lagtm(trans blas.Transpose, alpha float64, a Tridiagonal, b blas64.General, beta float64, c blas64.General) {
   454  	gonum.Implementation{}.Dlagtm(trans, c.Rows, c.Cols, alpha, a.DL, a.D, a.DU, b.Data, max(1, b.Stride), beta, c.Data, max(1, c.Stride))
   455  }
   456  
   457  // Lange computes the matrix norm of the general m×n matrix A. The input norm
   458  // specifies the norm computed.
   459  //  lapack.MaxAbs: the maximum absolute value of an element.
   460  //  lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries.
   461  //  lapack.MaxRowSum: the maximum row sum of the absolute values of the entries.
   462  //  lapack.Frobenius: the square root of the sum of the squares of the entries.
   463  // If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise.
   464  // There are no restrictions on work for the other matrix norms.
   465  func Lange(norm lapack.MatrixNorm, a blas64.General, work []float64) float64 {
   466  	return lapack64.Dlange(norm, a.Rows, a.Cols, a.Data, max(1, a.Stride), work)
   467  }
   468  
   469  // Langt computes the specified norm of an n×n tridiagonal matrix.
   470  //
   471  // Dlangt is not part of the lapack.Float64 interface and so calls to Langt are
   472  // always executed by the Gonum implementation.
   473  func Langt(norm lapack.MatrixNorm, a Tridiagonal) float64 {
   474  	return gonum.Implementation{}.Dlangt(norm, a.N, a.DL, a.D, a.DU)
   475  }
   476  
   477  // Lansb computes the specified norm of an n×n symmetric band matrix. If
   478  // norm == lapack.MaxColumnSum or norm == lapack.MaxRowSum, work must have length
   479  // at least n and this function will panic otherwise.
   480  // There are no restrictions on work for the other matrix norms.
   481  //
   482  // Dlansb is not part of the lapack.Float64 interface and so calls to Lansb are always
   483  // executed by the Gonum implementation.
   484  func Lansb(norm lapack.MatrixNorm, a blas64.SymmetricBand, work []float64) float64 {
   485  	return gonum.Implementation{}.Dlansb(norm, a.Uplo, a.N, a.K, a.Data, max(1, a.Stride), work)
   486  }
   487  
   488  // Lansy computes the specified norm of an n×n symmetric matrix. If
   489  // norm == lapack.MaxColumnSum or norm == lapack.MaxRowSum, work must have length
   490  // at least n and this function will panic otherwise.
   491  // There are no restrictions on work for the other matrix norms.
   492  func Lansy(norm lapack.MatrixNorm, a blas64.Symmetric, work []float64) float64 {
   493  	return lapack64.Dlansy(norm, a.Uplo, a.N, a.Data, max(1, a.Stride), work)
   494  }
   495  
   496  // Lantr computes the specified norm of an m×n trapezoidal matrix A. If
   497  // norm == lapack.MaxColumnSum work must have length at least n and this function
   498  // will panic otherwise. There are no restrictions on work for the other matrix norms.
   499  func Lantr(norm lapack.MatrixNorm, a blas64.Triangular, work []float64) float64 {
   500  	return lapack64.Dlantr(norm, a.Uplo, a.Diag, a.N, a.N, a.Data, max(1, a.Stride), work)
   501  }
   502  
   503  // Lantb computes the specified norm of an n×n triangular band matrix A. If
   504  // norm == lapack.MaxColumnSum work must have length at least n and this function
   505  // will panic otherwise. There are no restrictions on work for the other matrix
   506  // norms.
   507  func Lantb(norm lapack.MatrixNorm, a blas64.TriangularBand, work []float64) float64 {
   508  	return gonum.Implementation{}.Dlantb(norm, a.Uplo, a.Diag, a.N, a.K, a.Data, max(1, a.Stride), work)
   509  }
   510  
   511  // Lapmt rearranges the columns of the m×n matrix X as specified by the
   512  // permutation k_0, k_1, ..., k_{n-1} of the integers 0, ..., n-1.
   513  //
   514  // If forward is true a forward permutation is performed:
   515  //
   516  //  X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1.
   517  //
   518  // otherwise a backward permutation is performed:
   519  //
   520  //  X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1.
   521  //
   522  // k must have length n, otherwise Lapmt will panic. k is zero-indexed.
   523  func Lapmt(forward bool, x blas64.General, k []int) {
   524  	lapack64.Dlapmt(forward, x.Rows, x.Cols, x.Data, max(1, x.Stride), k)
   525  }
   526  
   527  // Ormlq multiplies the matrix C by the othogonal matrix Q defined by
   528  // A and tau. A and tau are as returned from Gelqf.
   529  //  C = Q * C   if side == blas.Left and trans == blas.NoTrans
   530  //  C = Qᵀ * C  if side == blas.Left and trans == blas.Trans
   531  //  C = C * Q   if side == blas.Right and trans == blas.NoTrans
   532  //  C = C * Qᵀ  if side == blas.Right and trans == blas.Trans
   533  // If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right
   534  // A is of size k×n. This uses a blocked algorithm.
   535  //
   536  // Work is temporary storage, and lwork specifies the usable memory length.
   537  // At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right,
   538  // and this function will panic otherwise.
   539  // Ormlq uses a block algorithm, but the block size is limited
   540  // by the temporary space available. If lwork == -1, instead of performing Ormlq,
   541  // the optimal work length will be stored into work[0].
   542  //
   543  // Tau contains the Householder scales and must have length at least k, and
   544  // this function will panic otherwise.
   545  func Ormlq(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) {
   546  	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)
   547  }
   548  
   549  // Ormqr multiplies an m×n matrix C by an orthogonal matrix Q as
   550  //  C = Q * C   if side == blas.Left  and trans == blas.NoTrans,
   551  //  C = Qᵀ * C  if side == blas.Left  and trans == blas.Trans,
   552  //  C = C * Q   if side == blas.Right and trans == blas.NoTrans,
   553  //  C = C * Qᵀ  if side == blas.Right and trans == blas.Trans,
   554  // where Q is defined as the product of k elementary reflectors
   555  //  Q = H_0 * H_1 * ... * H_{k-1}.
   556  //
   557  // If side == blas.Left, A is an m×k matrix and 0 <= k <= m.
   558  // If side == blas.Right, A is an n×k matrix and 0 <= k <= n.
   559  // The ith column of A contains the vector which defines the elementary
   560  // reflector H_i and tau[i] contains its scalar factor. tau must have length k
   561  // and Ormqr will panic otherwise. Geqrf returns A and tau in the required
   562  // form.
   563  //
   564  // work must have length at least max(1,lwork), and lwork must be at least n if
   565  // side == blas.Left and at least m if side == blas.Right, otherwise Ormqr will
   566  // panic.
   567  //
   568  // work is temporary storage, and lwork specifies the usable memory length. At
   569  // minimum, lwork >= m if side == blas.Left and lwork >= n if side ==
   570  // blas.Right, and this function will panic otherwise. Larger values of lwork
   571  // will generally give better performance. On return, work[0] will contain the
   572  // optimal value of lwork.
   573  //
   574  // If lwork is -1, instead of performing Ormqr, the optimal workspace size will
   575  // be stored into work[0].
   576  func Ormqr(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) {
   577  	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)
   578  }
   579  
   580  // Pocon estimates the reciprocal of the condition number of a positive-definite
   581  // matrix A given the Cholesky decmposition of A. The condition number computed
   582  // is based on the 1-norm and the ∞-norm.
   583  //
   584  // anorm is the 1-norm and the ∞-norm of the original matrix A.
   585  //
   586  // work is a temporary data slice of length at least 3*n and Pocon will panic otherwise.
   587  //
   588  // iwork is a temporary data slice of length at least n and Pocon will panic otherwise.
   589  func Pocon(a blas64.Symmetric, anorm float64, work []float64, iwork []int) float64 {
   590  	return lapack64.Dpocon(a.Uplo, a.N, a.Data, max(1, a.Stride), anorm, work, iwork)
   591  }
   592  
   593  // Syev computes all eigenvalues and, optionally, the eigenvectors of a real
   594  // symmetric matrix A.
   595  //
   596  // w contains the eigenvalues in ascending order upon return. w must have length
   597  // at least n, and Syev will panic otherwise.
   598  //
   599  // On entry, a contains the elements of the symmetric matrix A in the triangular
   600  // portion specified by uplo. If jobz == lapack.EVCompute, a contains the
   601  // orthonormal eigenvectors of A on exit, otherwise jobz must be lapack.EVNone
   602  // and on exit the specified triangular region is overwritten.
   603  //
   604  // Work is temporary storage, and lwork specifies the usable memory length. At minimum,
   605  // lwork >= 3*n-1, and Syev will panic otherwise. The amount of blocking is
   606  // limited by the usable length. If lwork == -1, instead of computing Syev the
   607  // optimal work length is stored into work[0].
   608  func Syev(jobz lapack.EVJob, a blas64.Symmetric, w, work []float64, lwork int) (ok bool) {
   609  	return lapack64.Dsyev(jobz, a.Uplo, a.N, a.Data, max(1, a.Stride), w, work, lwork)
   610  }
   611  
   612  // Tbtrs solves a triangular system of the form
   613  //  A * X = B   if trans == blas.NoTrans
   614  //  Aᵀ * X = B  if trans == blas.Trans or blas.ConjTrans
   615  // where A is an n×n triangular band matrix, and B is an n×nrhs matrix.
   616  //
   617  // Tbtrs returns whether A is non-singular. If A is singular, no solutions X
   618  // are computed.
   619  func Tbtrs(trans blas.Transpose, a blas64.TriangularBand, b blas64.General) (ok bool) {
   620  	return lapack64.Dtbtrs(a.Uplo, trans, a.Diag, a.N, a.K, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride))
   621  }
   622  
   623  // Trcon estimates the reciprocal of the condition number of a triangular matrix A.
   624  // The condition number computed may be based on the 1-norm or the ∞-norm.
   625  //
   626  // work is a temporary data slice of length at least 3*n and Trcon will panic otherwise.
   627  //
   628  // iwork is a temporary data slice of length at least n and Trcon will panic otherwise.
   629  func Trcon(norm lapack.MatrixNorm, a blas64.Triangular, work []float64, iwork []int) float64 {
   630  	return lapack64.Dtrcon(norm, a.Uplo, a.Diag, a.N, a.Data, max(1, a.Stride), work, iwork)
   631  }
   632  
   633  // Trtri computes the inverse of a triangular matrix, storing the result in place
   634  // into a.
   635  //
   636  // Trtri will not perform the inversion if the matrix is singular, and returns
   637  // a boolean indicating whether the inversion was successful.
   638  func Trtri(a blas64.Triangular) (ok bool) {
   639  	return lapack64.Dtrtri(a.Uplo, a.Diag, a.N, a.Data, max(1, a.Stride))
   640  }
   641  
   642  // Trtrs solves a triangular system of the form A * X = B or Aᵀ * X = B. Trtrs
   643  // returns whether the solve completed successfully. If A is singular, no solve is performed.
   644  func Trtrs(trans blas.Transpose, a blas64.Triangular, b blas64.General) (ok bool) {
   645  	return lapack64.Dtrtrs(a.Uplo, trans, a.Diag, a.N, b.Cols, a.Data, max(1, a.Stride), b.Data, max(1, b.Stride))
   646  }
   647  
   648  // Geev computes the eigenvalues and, optionally, the left and/or right
   649  // eigenvectors for an n×n real nonsymmetric matrix A.
   650  //
   651  // The right eigenvector v_j of A corresponding to an eigenvalue λ_j
   652  // is defined by
   653  //  A v_j = λ_j v_j,
   654  // and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by
   655  //  u_jᴴ A = λ_j u_jᴴ,
   656  // where u_jᴴ is the conjugate transpose of u_j.
   657  //
   658  // On return, A will be overwritten and the left and right eigenvectors will be
   659  // stored, respectively, in the columns of the n×n matrices VL and VR in the
   660  // same order as their eigenvalues. If the j-th eigenvalue is real, then
   661  //  u_j = VL[:,j],
   662  //  v_j = VR[:,j],
   663  // and if it is not real, then j and j+1 form a complex conjugate pair and the
   664  // eigenvectors can be recovered as
   665  //  u_j     = VL[:,j] + i*VL[:,j+1],
   666  //  u_{j+1} = VL[:,j] - i*VL[:,j+1],
   667  //  v_j     = VR[:,j] + i*VR[:,j+1],
   668  //  v_{j+1} = VR[:,j] - i*VR[:,j+1],
   669  // where i is the imaginary unit. The computed eigenvectors are normalized to
   670  // have Euclidean norm equal to 1 and largest component real.
   671  //
   672  // Left eigenvectors will be computed only if jobvl == lapack.LeftEVCompute,
   673  // otherwise jobvl must be lapack.LeftEVNone.
   674  // Right eigenvectors will be computed only if jobvr == lapack.RightEVCompute,
   675  // otherwise jobvr must be lapack.RightEVNone.
   676  // For other values of jobvl and jobvr Geev will panic.
   677  //
   678  // On return, wr and wi will contain the real and imaginary parts, respectively,
   679  // of the computed eigenvalues. Complex conjugate pairs of eigenvalues appear
   680  // consecutively with the eigenvalue having the positive imaginary part first.
   681  // wr and wi must have length n, and Geev will panic otherwise.
   682  //
   683  // work must have length at least lwork and lwork must be at least max(1,4*n) if
   684  // the left or right eigenvectors are computed, and at least max(1,3*n) if no
   685  // eigenvectors are computed. For good performance, lwork must generally be
   686  // larger. On return, optimal value of lwork will be stored in work[0].
   687  //
   688  // If lwork == -1, instead of performing Geev, the function only calculates the
   689  // optimal vaule of lwork and stores it into work[0].
   690  //
   691  // On return, first will be the index of the first valid eigenvalue.
   692  // If first == 0, all eigenvalues and eigenvectors have been computed.
   693  // If first is positive, Geev failed to compute all the eigenvalues, no
   694  // eigenvectors have been computed and wr[first:] and wi[first:] contain those
   695  // eigenvalues which have converged.
   696  func Geev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, a blas64.General, wr, wi []float64, vl, vr blas64.General, work []float64, lwork int) (first int) {
   697  	n := a.Rows
   698  	if a.Cols != n {
   699  		panic("lapack64: matrix not square")
   700  	}
   701  	if jobvl == lapack.LeftEVCompute && (vl.Rows != n || vl.Cols != n) {
   702  		panic("lapack64: bad size of VL")
   703  	}
   704  	if jobvr == lapack.RightEVCompute && (vr.Rows != n || vr.Cols != n) {
   705  		panic("lapack64: bad size of VR")
   706  	}
   707  	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)
   708  }