github.com/gonum/lapack@v0.0.0-20181123203213-e4cdc5a0bff9/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  // This repository is no longer maintained.
     6  // Development has moved to https://github.com/gonum/gonum.
     7  //
     8  // Package lapack64 provides a set of convenient wrapper functions for LAPACK
     9  // calls, as specified in the netlib standard (www.netlib.org).
    10  //
    11  // The native Go routines are used by default, and the Use function can be used
    12  // to set an alternative implementation.
    13  //
    14  // If the type of matrix (General, Symmetric, etc.) is known and fixed, it is
    15  // used in the wrapper signature. In many cases, however, the type of the matrix
    16  // changes during the call to the routine, for example the matrix is symmetric on
    17  // entry and is triangular on exit. In these cases the correct types should be checked
    18  // in the documentation.
    19  //
    20  // The full set of Lapack functions is very large, and it is not clear that a
    21  // full implementation is desirable, let alone feasible. Please open up an issue
    22  // if there is a specific function you need and/or are willing to implement.
    23  package lapack64
    24  
    25  import (
    26  	"github.com/gonum/blas"
    27  	"github.com/gonum/blas/blas64"
    28  	"github.com/gonum/lapack"
    29  	"github.com/gonum/lapack/native"
    30  )
    31  
    32  var lapack64 lapack.Float64 = native.Implementation{}
    33  
    34  // Use sets the LAPACK float64 implementation to be used by subsequent BLAS calls.
    35  // The default implementation is native.Implementation.
    36  func Use(l lapack.Float64) {
    37  	lapack64 = l
    38  }
    39  
    40  // Potrf computes the Cholesky factorization of a.
    41  // The factorization has the form
    42  //  A = U^T * U if a.Uplo == blas.Upper, or
    43  //  A = L * L^T if a.Uplo == blas.Lower,
    44  // where U is an upper triangular matrix and L is lower triangular.
    45  // The triangular matrix is returned in t, and the underlying data between
    46  // a and t is shared. The returned bool indicates whether a is positive
    47  // definite and the factorization could be finished.
    48  func Potrf(a blas64.Symmetric) (t blas64.Triangular, ok bool) {
    49  	ok = lapack64.Dpotrf(a.Uplo, a.N, a.Data, a.Stride)
    50  	t.Uplo = a.Uplo
    51  	t.N = a.N
    52  	t.Data = a.Data
    53  	t.Stride = a.Stride
    54  	t.Diag = blas.NonUnit
    55  	return
    56  }
    57  
    58  // Gecon estimates the reciprocal of the condition number of the n×n matrix A
    59  // given the LU decomposition of the matrix. The condition number computed may
    60  // be based on the 1-norm or the ∞-norm.
    61  //
    62  // a contains the result of the LU decomposition of A as computed by Getrf.
    63  //
    64  // anorm is the corresponding 1-norm or ∞-norm of the original matrix A.
    65  //
    66  // work is a temporary data slice of length at least 4*n and Gecon will panic otherwise.
    67  //
    68  // iwork is a temporary data slice of length at least n and Gecon will panic otherwise.
    69  func Gecon(norm lapack.MatrixNorm, a blas64.General, anorm float64, work []float64, iwork []int) float64 {
    70  	return lapack64.Dgecon(norm, a.Cols, a.Data, a.Stride, anorm, work, iwork)
    71  }
    72  
    73  // Gels finds a minimum-norm solution based on the matrices A and B using the
    74  // QR or LQ factorization. Gels returns false if the matrix
    75  // A is singular, and true if this solution was successfully found.
    76  //
    77  // The minimization problem solved depends on the input parameters.
    78  //
    79  //  1. If m >= n and trans == blas.NoTrans, Gels finds X such that || A*X - B||_2
    80  //     is minimized.
    81  //  2. If m < n and trans == blas.NoTrans, Gels finds the minimum norm solution of
    82  //     A * X = B.
    83  //  3. If m >= n and trans == blas.Trans, Gels finds the minimum norm solution of
    84  //     A^T * X = B.
    85  //  4. If m < n and trans == blas.Trans, Gels finds X such that || A*X - B||_2
    86  //     is minimized.
    87  // Note that the least-squares solutions (cases 1 and 3) perform the minimization
    88  // per column of B. This is not the same as finding the minimum-norm matrix.
    89  //
    90  // The matrix A is a general matrix of size m×n and is modified during this call.
    91  // The input matrix B is of size max(m,n)×nrhs, and serves two purposes. On entry,
    92  // the elements of b specify the input matrix B. B has size m×nrhs if
    93  // trans == blas.NoTrans, and n×nrhs if trans == blas.Trans. On exit, the
    94  // leading submatrix of b contains the solution vectors X. If trans == blas.NoTrans,
    95  // this submatrix is of size n×nrhs, and of size m×nrhs otherwise.
    96  //
    97  // Work is temporary storage, and lwork specifies the usable memory length.
    98  // At minimum, lwork >= max(m,n) + max(m,n,nrhs), and this function will panic
    99  // otherwise. A longer work will enable blocked algorithms to be called.
   100  // In the special case that lwork == -1, work[0] will be set to the optimal working
   101  // length.
   102  func Gels(trans blas.Transpose, a blas64.General, b blas64.General, work []float64, lwork int) bool {
   103  	return lapack64.Dgels(trans, a.Rows, a.Cols, b.Cols, a.Data, a.Stride, b.Data, b.Stride, work, lwork)
   104  }
   105  
   106  // Geqrf computes the QR factorization of the m×n matrix A using a blocked
   107  // algorithm. A is modified to contain the information to construct Q and R.
   108  // The upper triangle of a contains the matrix R. The lower triangular elements
   109  // (not including the diagonal) contain the elementary reflectors. tau is modified
   110  // to contain the reflector scales. tau must have length at least min(m,n), and
   111  // this function will panic otherwise.
   112  //
   113  // The ith elementary reflector can be explicitly constructed by first extracting
   114  // the
   115  //  v[j] = 0           j < i
   116  //  v[j] = 1           j == i
   117  //  v[j] = a[j*lda+i]  j > i
   118  // and computing H_i = I - tau[i] * v * v^T.
   119  //
   120  // The orthonormal matrix Q can be constucted from a product of these elementary
   121  // reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n).
   122  //
   123  // Work is temporary storage, and lwork specifies the usable memory length.
   124  // At minimum, lwork >= m and this function will panic otherwise.
   125  // Geqrf is a blocked QR factorization, but the block size is limited
   126  // by the temporary space available. If lwork == -1, instead of performing Geqrf,
   127  // the optimal work length will be stored into work[0].
   128  func Geqrf(a blas64.General, tau, work []float64, lwork int) {
   129  	lapack64.Dgeqrf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork)
   130  }
   131  
   132  // Gelqf computes the LQ factorization of the m×n matrix A using a blocked
   133  // algorithm. A is modified to contain the information to construct L and Q. The
   134  // lower triangle of a contains the matrix L. The elements above the diagonal
   135  // and the slice tau represent the matrix Q. tau is modified to contain the
   136  // reflector scales. tau must have length at least min(m,n), and this function
   137  // will panic otherwise.
   138  //
   139  // See Geqrf for a description of the elementary reflectors and orthonormal
   140  // matrix Q. Q is constructed as a product of these elementary reflectors,
   141  // Q = H_{k-1} * ... * H_1 * H_0.
   142  //
   143  // Work is temporary storage, and lwork specifies the usable memory length.
   144  // At minimum, lwork >= m and this function will panic otherwise.
   145  // Gelqf is a blocked LQ factorization, but the block size is limited
   146  // by the temporary space available. If lwork == -1, instead of performing Gelqf,
   147  // the optimal work length will be stored into work[0].
   148  func Gelqf(a blas64.General, tau, work []float64, lwork int) {
   149  	lapack64.Dgelqf(a.Rows, a.Cols, a.Data, a.Stride, tau, work, lwork)
   150  }
   151  
   152  // Gesvd computes the singular value decomposition of the input matrix A.
   153  //
   154  // The singular value decomposition is
   155  //  A = U * Sigma * V^T
   156  // where Sigma is an m×n diagonal matrix containing the singular values of A,
   157  // U is an m×m orthogonal matrix and V is an n×n orthogonal matrix. The first
   158  // min(m,n) columns of U and V are the left and right singular vectors of A
   159  // respectively.
   160  //
   161  // jobU and jobVT are options for computing the singular vectors. The behavior
   162  // is as follows
   163  //  jobU == lapack.SVDAll       All m columns of U are returned in u
   164  //  jobU == lapack.SVDInPlace   The first min(m,n) columns are returned in u
   165  //  jobU == lapack.SVDOverwrite The first min(m,n) columns of U are written into a
   166  //  jobU == lapack.SVDNone      The columns of U are not computed.
   167  // The behavior is the same for jobVT and the rows of V^T. At most one of jobU
   168  // and jobVT can equal lapack.SVDOverwrite, and Gesvd will panic otherwise.
   169  //
   170  // On entry, a contains the data for the m×n matrix A. During the call to Gesvd
   171  // the data is overwritten. On exit, A contains the appropriate singular vectors
   172  // if either job is lapack.SVDOverwrite.
   173  //
   174  // s is a slice of length at least min(m,n) and on exit contains the singular
   175  // values in decreasing order.
   176  //
   177  // u contains the left singular vectors on exit, stored columnwise. If
   178  // jobU == lapack.SVDAll, u is of size m×m. If jobU == lapack.SVDInPlace u is
   179  // of size m×min(m,n). If jobU == lapack.SVDOverwrite or lapack.SVDNone, u is
   180  // not used.
   181  //
   182  // vt contains the left singular vectors on exit, stored rowwise. If
   183  // jobV == lapack.SVDAll, vt is of size n×m. If jobVT == lapack.SVDInPlace vt is
   184  // of size min(m,n)×n. If jobVT == lapack.SVDOverwrite or lapack.SVDNone, vt is
   185  // not used.
   186  //
   187  // work is a slice for storing temporary memory, and lwork is the usable size of
   188  // the slice. lwork must be at least max(5*min(m,n), 3*min(m,n)+max(m,n)).
   189  // If lwork == -1, instead of performing Gesvd, the optimal work length will be
   190  // stored into work[0]. Gesvd will panic if the working memory has insufficient
   191  // storage.
   192  //
   193  // Gesvd returns whether the decomposition successfully completed.
   194  func Gesvd(jobU, jobVT lapack.SVDJob, a, u, vt blas64.General, s, work []float64, lwork int) (ok bool) {
   195  	return lapack64.Dgesvd(jobU, jobVT, a.Rows, a.Cols, a.Data, a.Stride, s, u.Data, u.Stride, vt.Data, vt.Stride, work, lwork)
   196  }
   197  
   198  // Getrf computes the LU decomposition of the m×n matrix A.
   199  // The LU decomposition is a factorization of A into
   200  //  A = P * L * U
   201  // where P is a permutation matrix, L is a unit lower triangular matrix, and
   202  // U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored
   203  // in place into a.
   204  //
   205  // ipiv is a permutation vector. It indicates that row i of the matrix was
   206  // changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic
   207  // otherwise. ipiv is zero-indexed.
   208  //
   209  // Getrf is the blocked version of the algorithm.
   210  //
   211  // Getrf returns whether the matrix A is singular. The LU decomposition will
   212  // be computed regardless of the singularity of A, but division by zero
   213  // will occur if the false is returned and the result is used to solve a
   214  // system of equations.
   215  func Getrf(a blas64.General, ipiv []int) bool {
   216  	return lapack64.Dgetrf(a.Rows, a.Cols, a.Data, a.Stride, ipiv)
   217  }
   218  
   219  // Getri computes the inverse of the matrix A using the LU factorization computed
   220  // by Getrf. On entry, a contains the PLU decomposition of A as computed by
   221  // Getrf and on exit contains the reciprocal of the original matrix.
   222  //
   223  // Getri will not perform the inversion if the matrix is singular, and returns
   224  // a boolean indicating whether the inversion was successful.
   225  //
   226  // Work is temporary storage, and lwork specifies the usable memory length.
   227  // At minimum, lwork >= n and this function will panic otherwise.
   228  // Getri is a blocked inversion, but the block size is limited
   229  // by the temporary space available. If lwork == -1, instead of performing Getri,
   230  // the optimal work length will be stored into work[0].
   231  func Getri(a blas64.General, ipiv []int, work []float64, lwork int) (ok bool) {
   232  	return lapack64.Dgetri(a.Cols, a.Data, a.Stride, ipiv, work, lwork)
   233  }
   234  
   235  // Getrs solves a system of equations using an LU factorization.
   236  // The system of equations solved is
   237  //  A * X = B if trans == blas.Trans
   238  //  A^T * X = B if trans == blas.NoTrans
   239  // A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs.
   240  //
   241  // On entry b contains the elements of the matrix B. On exit, b contains the
   242  // elements of X, the solution to the system of equations.
   243  //
   244  // a and ipiv contain the LU factorization of A and the permutation indices as
   245  // computed by Getrf. ipiv is zero-indexed.
   246  func Getrs(trans blas.Transpose, a blas64.General, b blas64.General, ipiv []int) {
   247  	lapack64.Dgetrs(trans, a.Cols, b.Cols, a.Data, a.Stride, ipiv, b.Data, b.Stride)
   248  }
   249  
   250  // Ggsvd3 computes the generalized singular value decomposition (GSVD)
   251  // of an m×n matrix A and p×n matrix B:
   252  //  U^T*A*Q = D1*[ 0 R ]
   253  //
   254  //  V^T*B*Q = D2*[ 0 R ]
   255  // where U, V and Q are orthogonal matrices.
   256  //
   257  // Ggsvd3 returns k and l, the dimensions of the sub-blocks. k+l
   258  // is the effective numerical rank of the (m+p)×n matrix [ A^T B^T ]^T.
   259  // R is a (k+l)×(k+l) nonsingular upper triangular matrix, D1 and
   260  // D2 are m×(k+l) and p×(k+l) diagonal matrices and of the following
   261  // structures, respectively:
   262  //
   263  // If m-k-l >= 0,
   264  //
   265  //                    k  l
   266  //       D1 =     k [ I  0 ]
   267  //                l [ 0  C ]
   268  //            m-k-l [ 0  0 ]
   269  //
   270  //                  k  l
   271  //       D2 = l   [ 0  S ]
   272  //            p-l [ 0  0 ]
   273  //
   274  //               n-k-l  k    l
   275  //  [ 0 R ] = k [  0   R11  R12 ] k
   276  //            l [  0    0   R22 ] l
   277  //
   278  // where
   279  //
   280  //  C = diag( alpha_k, ... , alpha_{k+l} ),
   281  //  S = diag( beta_k,  ... , beta_{k+l} ),
   282  //  C^2 + S^2 = I.
   283  //
   284  // R is stored in
   285  //  A[0:k+l, n-k-l:n]
   286  // on exit.
   287  //
   288  // If m-k-l < 0,
   289  //
   290  //                 k m-k k+l-m
   291  //      D1 =   k [ I  0    0  ]
   292  //           m-k [ 0  C    0  ]
   293  //
   294  //                   k m-k k+l-m
   295  //      D2 =   m-k [ 0  S    0  ]
   296  //           k+l-m [ 0  0    I  ]
   297  //             p-l [ 0  0    0  ]
   298  //
   299  //                 n-k-l  k   m-k  k+l-m
   300  //  [ 0 R ] =    k [ 0    R11  R12  R13 ]
   301  //             m-k [ 0     0   R22  R23 ]
   302  //           k+l-m [ 0     0    0   R33 ]
   303  //
   304  // where
   305  //  C = diag( alpha_k, ... , alpha_m ),
   306  //  S = diag( beta_k,  ... , beta_m ),
   307  //  C^2 + S^2 = I.
   308  //
   309  //  R = [ R11 R12 R13 ] is stored in A[1:m, n-k-l+1:n]
   310  //      [  0  R22 R23 ]
   311  // and R33 is stored in
   312  //  B[m-k:l, n+m-k-l:n] on exit.
   313  //
   314  // Ggsvd3 computes C, S, R, and optionally the orthogonal transformation
   315  // matrices U, V and Q.
   316  //
   317  // jobU, jobV and jobQ are options for computing the orthogonal matrices. The behavior
   318  // is as follows
   319  //  jobU == lapack.GSVDU        Compute orthogonal matrix U
   320  //  jobU == lapack.GSVDNone     Do not compute orthogonal matrix.
   321  // The behavior is the same for jobV and jobQ with the exception that instead of
   322  // lapack.GSVDU these accept lapack.GSVDV and lapack.GSVDQ respectively.
   323  // The matrices U, V and Q must be m×m, p×p and n×n respectively unless the
   324  // relevant job parameter is lapack.GSVDNone.
   325  //
   326  // alpha and beta must have length n or Ggsvd3 will panic. On exit, alpha and
   327  // beta contain the generalized singular value pairs of A and B
   328  //   alpha[0:k] = 1,
   329  //   beta[0:k]  = 0,
   330  // if m-k-l >= 0,
   331  //   alpha[k:k+l] = diag(C),
   332  //   beta[k:k+l]  = diag(S),
   333  // if m-k-l < 0,
   334  //   alpha[k:m]= C, alpha[m:k+l]= 0
   335  //   beta[k:m] = S, beta[m:k+l] = 1.
   336  // if k+l < n,
   337  //   alpha[k+l:n] = 0 and
   338  //   beta[k+l:n]  = 0.
   339  //
   340  // On exit, iwork contains the permutation required to sort alpha descending.
   341  //
   342  // iwork must have length n, work must have length at least max(1, lwork), and
   343  // lwork must be -1 or greater than n, otherwise Ggsvd3 will panic. If
   344  // lwork is -1, work[0] holds the optimal lwork on return, but Ggsvd3 does
   345  // not perform the GSVD.
   346  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) {
   347  	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)
   348  }
   349  
   350  // Lange computes the matrix norm of the general m×n matrix A. The input norm
   351  // specifies the norm computed.
   352  //  lapack.MaxAbs: the maximum absolute value of an element.
   353  //  lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries.
   354  //  lapack.MaxRowSum: the maximum row sum of the absolute values of the entries.
   355  //  lapack.Frobenius: the square root of the sum of the squares of the entries.
   356  // If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise.
   357  // There are no restrictions on work for the other matrix norms.
   358  func Lange(norm lapack.MatrixNorm, a blas64.General, work []float64) float64 {
   359  	return lapack64.Dlange(norm, a.Rows, a.Cols, a.Data, a.Stride, work)
   360  }
   361  
   362  // Lansy computes the specified norm of an n×n symmetric matrix. If
   363  // norm == lapack.MaxColumnSum or norm == lapackMaxRowSum work must have length
   364  // at least n and this function will panic otherwise.
   365  // There are no restrictions on work for the other matrix norms.
   366  func Lansy(norm lapack.MatrixNorm, a blas64.Symmetric, work []float64) float64 {
   367  	return lapack64.Dlansy(norm, a.Uplo, a.N, a.Data, a.Stride, work)
   368  }
   369  
   370  // Lantr computes the specified norm of an m×n trapezoidal matrix A. If
   371  // norm == lapack.MaxColumnSum work must have length at least n and this function
   372  // will panic otherwise. There are no restrictions on work for the other matrix norms.
   373  func Lantr(norm lapack.MatrixNorm, a blas64.Triangular, work []float64) float64 {
   374  	return lapack64.Dlantr(norm, a.Uplo, a.Diag, a.N, a.N, a.Data, a.Stride, work)
   375  }
   376  
   377  // Lapmt rearranges the columns of the m×n matrix X as specified by the
   378  // permutation k_0, k_1, ..., k_{n-1} of the integers 0, ..., n-1.
   379  //
   380  // If forward is true a forward permutation is performed:
   381  //
   382  //  X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1.
   383  //
   384  // otherwise a backward permutation is performed:
   385  //
   386  //  X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1.
   387  //
   388  // k must have length n, otherwise Lapmt will panic. k is zero-indexed.
   389  func Lapmt(forward bool, x blas64.General, k []int) {
   390  	lapack64.Dlapmt(forward, x.Rows, x.Cols, x.Data, x.Stride, k)
   391  }
   392  
   393  // Ormlq multiplies the matrix C by the othogonal matrix Q defined by
   394  // A and tau. A and tau are as returned from Gelqf.
   395  //  C = Q * C    if side == blas.Left and trans == blas.NoTrans
   396  //  C = Q^T * C  if side == blas.Left and trans == blas.Trans
   397  //  C = C * Q    if side == blas.Right and trans == blas.NoTrans
   398  //  C = C * Q^T  if side == blas.Right and trans == blas.Trans
   399  // If side == blas.Left, A is a matrix of side k×m, and if side == blas.Right
   400  // A is of size k×n. This uses a blocked algorithm.
   401  //
   402  // Work is temporary storage, and lwork specifies the usable memory length.
   403  // At minimum, lwork >= m if side == blas.Left and lwork >= n if side == blas.Right,
   404  // and this function will panic otherwise.
   405  // Ormlq uses a block algorithm, but the block size is limited
   406  // by the temporary space available. If lwork == -1, instead of performing Ormlq,
   407  // the optimal work length will be stored into work[0].
   408  //
   409  // Tau contains the Householder scales and must have length at least k, and
   410  // this function will panic otherwise.
   411  func Ormlq(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) {
   412  	lapack64.Dormlq(side, trans, c.Rows, c.Cols, a.Rows, a.Data, a.Stride, tau, c.Data, c.Stride, work, lwork)
   413  }
   414  
   415  // Ormqr multiplies an m×n matrix C by an orthogonal matrix Q as
   416  //  C = Q * C,    if side == blas.Left  and trans == blas.NoTrans,
   417  //  C = Q^T * C,  if side == blas.Left  and trans == blas.Trans,
   418  //  C = C * Q,    if side == blas.Right and trans == blas.NoTrans,
   419  //  C = C * Q^T,  if side == blas.Right and trans == blas.Trans,
   420  // where Q is defined as the product of k elementary reflectors
   421  //  Q = H_0 * H_1 * ... * H_{k-1}.
   422  //
   423  // If side == blas.Left, A is an m×k matrix and 0 <= k <= m.
   424  // If side == blas.Right, A is an n×k matrix and 0 <= k <= n.
   425  // The ith column of A contains the vector which defines the elementary
   426  // reflector H_i and tau[i] contains its scalar factor. tau must have length k
   427  // and Ormqr will panic otherwise. Geqrf returns A and tau in the required
   428  // form.
   429  //
   430  // work must have length at least max(1,lwork), and lwork must be at least n if
   431  // side == blas.Left and at least m if side == blas.Right, otherwise Ormqr will
   432  // panic.
   433  //
   434  // work is temporary storage, and lwork specifies the usable memory length. At
   435  // minimum, lwork >= m if side == blas.Left and lwork >= n if side ==
   436  // blas.Right, and this function will panic otherwise. Larger values of lwork
   437  // will generally give better performance. On return, work[0] will contain the
   438  // optimal value of lwork.
   439  //
   440  // If lwork is -1, instead of performing Ormqr, the optimal workspace size will
   441  // be stored into work[0].
   442  func Ormqr(side blas.Side, trans blas.Transpose, a blas64.General, tau []float64, c blas64.General, work []float64, lwork int) {
   443  	lapack64.Dormqr(side, trans, c.Rows, c.Cols, a.Cols, a.Data, a.Stride, tau, c.Data, c.Stride, work, lwork)
   444  }
   445  
   446  // Pocon estimates the reciprocal of the condition number of a positive-definite
   447  // matrix A given the Cholesky decmposition of A. The condition number computed
   448  // is based on the 1-norm and the ∞-norm.
   449  //
   450  // anorm is the 1-norm and the ∞-norm of the original matrix A.
   451  //
   452  // work is a temporary data slice of length at least 3*n and Pocon will panic otherwise.
   453  //
   454  // iwork is a temporary data slice of length at least n and Pocon will panic otherwise.
   455  func Pocon(a blas64.Symmetric, anorm float64, work []float64, iwork []int) float64 {
   456  	return lapack64.Dpocon(a.Uplo, a.N, a.Data, a.Stride, anorm, work, iwork)
   457  }
   458  
   459  // Syev computes all eigenvalues and, optionally, the eigenvectors of a real
   460  // symmetric matrix A.
   461  //
   462  // w contains the eigenvalues in ascending order upon return. w must have length
   463  // at least n, and Syev will panic otherwise.
   464  //
   465  // On entry, a contains the elements of the symmetric matrix A in the triangular
   466  // portion specified by uplo. If jobz == lapack.ComputeEV a contains the
   467  // orthonormal eigenvectors of A on exit, otherwise on exit the specified
   468  // triangular region is overwritten.
   469  //
   470  // Work is temporary storage, and lwork specifies the usable memory length. At minimum,
   471  // lwork >= 3*n-1, and Syev will panic otherwise. The amount of blocking is
   472  // limited by the usable length. If lwork == -1, instead of computing Syev the
   473  // optimal work length is stored into work[0].
   474  func Syev(jobz lapack.EVJob, a blas64.Symmetric, w, work []float64, lwork int) (ok bool) {
   475  	return lapack64.Dsyev(jobz, a.Uplo, a.N, a.Data, a.Stride, w, work, lwork)
   476  }
   477  
   478  // Trcon estimates the reciprocal of the condition number of a triangular matrix A.
   479  // The condition number computed may be based on the 1-norm or the ∞-norm.
   480  //
   481  // work is a temporary data slice of length at least 3*n and Trcon will panic otherwise.
   482  //
   483  // iwork is a temporary data slice of length at least n and Trcon will panic otherwise.
   484  func Trcon(norm lapack.MatrixNorm, a blas64.Triangular, work []float64, iwork []int) float64 {
   485  	return lapack64.Dtrcon(norm, a.Uplo, a.Diag, a.N, a.Data, a.Stride, work, iwork)
   486  }
   487  
   488  // Trtri computes the inverse of a triangular matrix, storing the result in place
   489  // into a.
   490  //
   491  // Trtri will not perform the inversion if the matrix is singular, and returns
   492  // a boolean indicating whether the inversion was successful.
   493  func Trtri(a blas64.Triangular) (ok bool) {
   494  	return lapack64.Dtrtri(a.Uplo, a.Diag, a.N, a.Data, a.Stride)
   495  }
   496  
   497  // Trtrs solves a triangular system of the form A * X = B or A^T * X = B. Trtrs
   498  // returns whether the solve completed successfully. If A is singular, no solve is performed.
   499  func Trtrs(trans blas.Transpose, a blas64.Triangular, b blas64.General) (ok bool) {
   500  	return lapack64.Dtrtrs(a.Uplo, trans, a.Diag, a.N, b.Cols, a.Data, a.Stride, b.Data, b.Stride)
   501  }
   502  
   503  // Geev computes the eigenvalues and, optionally, the left and/or right
   504  // eigenvectors for an n×n real nonsymmetric matrix A.
   505  //
   506  // The right eigenvector v_j of A corresponding to an eigenvalue λ_j
   507  // is defined by
   508  //  A v_j = λ_j v_j,
   509  // and the left eigenvector u_j corresponding to an eigenvalue λ_j is defined by
   510  //  u_j^H A = λ_j u_j^H,
   511  // where u_j^H is the conjugate transpose of u_j.
   512  //
   513  // On return, A will be overwritten and the left and right eigenvectors will be
   514  // stored, respectively, in the columns of the n×n matrices VL and VR in the
   515  // same order as their eigenvalues. If the j-th eigenvalue is real, then
   516  //  u_j = VL[:,j],
   517  //  v_j = VR[:,j],
   518  // and if it is not real, then j and j+1 form a complex conjugate pair and the
   519  // eigenvectors can be recovered as
   520  //  u_j     = VL[:,j] + i*VL[:,j+1],
   521  //  u_{j+1} = VL[:,j] - i*VL[:,j+1],
   522  //  v_j     = VR[:,j] + i*VR[:,j+1],
   523  //  v_{j+1} = VR[:,j] - i*VR[:,j+1],
   524  // where i is the imaginary unit. The computed eigenvectors are normalized to
   525  // have Euclidean norm equal to 1 and largest component real.
   526  //
   527  // Left eigenvectors will be computed only if jobvl == lapack.ComputeLeftEV,
   528  // otherwise jobvl must be lapack.None.
   529  // Right eigenvectors will be computed only if jobvr == lapack.ComputeRightEV,
   530  // otherwise jobvr must be lapack.None.
   531  // For other values of jobvl and jobvr Geev will panic.
   532  //
   533  // On return, wr and wi will contain the real and imaginary parts, respectively,
   534  // of the computed eigenvalues. Complex conjugate pairs of eigenvalues appear
   535  // consecutively with the eigenvalue having the positive imaginary part first.
   536  // wr and wi must have length n, and Geev will panic otherwise.
   537  //
   538  // work must have length at least lwork and lwork must be at least max(1,4*n) if
   539  // the left or right eigenvectors are computed, and at least max(1,3*n) if no
   540  // eigenvectors are computed. For good performance, lwork must generally be
   541  // larger. On return, optimal value of lwork will be stored in work[0].
   542  //
   543  // If lwork == -1, instead of performing Geev, the function only calculates the
   544  // optimal vaule of lwork and stores it into work[0].
   545  //
   546  // On return, first will be the index of the first valid eigenvalue.
   547  // If first == 0, all eigenvalues and eigenvectors have been computed.
   548  // If first is positive, Geev failed to compute all the eigenvalues, no
   549  // eigenvectors have been computed and wr[first:] and wi[first:] contain those
   550  // eigenvalues which have converged.
   551  func Geev(jobvl lapack.LeftEVJob, jobvr lapack.RightEVJob, a blas64.General, wr, wi []float64, vl, vr blas64.General, work []float64, lwork int) (first int) {
   552  	n := a.Rows
   553  	if a.Cols != n {
   554  		panic("lapack64: matrix not square")
   555  	}
   556  	if jobvl == lapack.ComputeLeftEV && (vl.Rows != n || vl.Cols != n) {
   557  		panic("lapack64: bad size of VL")
   558  	}
   559  	if jobvr == lapack.ComputeRightEV && (vr.Rows != n || vr.Cols != n) {
   560  		panic("lapack64: bad size of VR")
   561  	}
   562  	return lapack64.Dgeev(jobvl, jobvr, n, a.Data, a.Stride, wr, wi, vl.Data, vl.Stride, vr.Data, vr.Stride, work, lwork)
   563  }