14

Is there a function in LAPACK, which will give me the elements of a particular submatrix? If so how what is the syntax in C++?

Or do I need to code it up?

  • Have a look at the [Armadillo C++ library](http://arma.sourceforge.net), which uses LAPACK and provides [submatrix views](http://arma.sourceforge.net/docs.html#submat). For example, X.submat(4,5,9,10) = ... – mtall Dec 12 '13 at 09:25

1 Answers1

26

There is no function for accessing a submatrix. However, because of the way matrix data is stored in LAPACK routines, you don't need one. This saves a lot of copying, and the data layout was (partially) chosen for this reason:

Recall that a dense (i.e., not banded, triangular, hermitian, etc) matrix in LAPACK is defined by four values:

  • a pointer to the top left corner of the matrix
  • the number of rows in the matrix
  • the number of columns in the matrix
  • the "leading dimension" of the matrix; typically this is the distance in memory between adjacent elements of a row.

Most of the time, most people only ever use a leading dimension that is equal to the number of rows; a 3x3 matrix is typically stored like so:

a[0] a[3] a[6] 
a[1] a[4] a[7]
a[2] a[5] a[8]

Suppose instead that we wanted a 3x3 submatrix of a huge matrix with leading dimension lda. Suppose we specifically want the 3x3 submatrix whose top-left corner is located at a(15,42):

         .             .            .
         .             .            .
... a[15+42*lda] a[15+43*lda] a[15+44*lda] ...
... a[16+42*lda] a[16+43*lda] a[16+44*lda] ...
... a[17+42*lda] a[17+43*lda] a[17+44*lda] ...
         .             .            .
         .             .            .

We could copy this 3x3 matrix into contiguous storage, but if we want to pass it as an input (or output) matrix to an LAPACK routine, we don't need to; we only need to define the parameters appropriately. Let's call this submatrix b; we then define:

// pointer to the top-left corner of b:
float *b = &a[15 + 42*lda];
// number of rows in b:
const int nb = 3;
// number of columns in b:
const int mb = 3;
// leading dimension of b:
const int ldb = lda;

The only thing that might be surprising is the value of ldb; by using the value lda of the "big matrix", we can address the submatrix without copying, and operate on it in-place.

However I lied (sort of). Sometimes you really can't operate on a submatrix in place, and genuinely need to copy it. I didn't want to talk about that, because it's rare, and you should use in-place operations whenever possible, but I would feel bad not telling you that it is possible. The routine:

SLACPY(UPLO,M,N,A,LDA,B,LDB)

copies the MxN matrix whose top-left corner is A and is stored with leading dimension LDA to the MxN matrix whose top-left corner is B and has leading dimension LDB. The UPLO parameter indicates whether to copy the upper triangle, lower triangle, or the whole matrix.

In the example I gave above, you would use it like this (assuming the clapack bindings):

...
const int m = 3;
const int n = 3;
float b[9];
const int ldb = 3;
slacpy("A",  // anything except "U" or "L" means "copy everything"
       &m,   // number of rows to copy
       &n,   // number of columns to copy
       &a[15 + 42*lda], // pointer to top-left element to copy
       lda,  // leading dimension of a (something huge)
       b,    // pointer to top-left element of destination
       ldb); // leading dimension of b (== m, so storage is dense)
...
Community
  • 1
  • 1
Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • 1
    great answer @Stephen; do you know if this approach to pass a submatrix can be easily generalized to passing a certain Minor of a matrix? say a 3x3 subminor containing only rows a,b,c and columns x,y,z – lurscher Feb 17 '11 at 18:05
  • @lurscher: No, in general this does not suffice to pull out minors. For that you need to do something more clever. – Stephen Canon Feb 17 '11 at 19:11
  • 1
    thanks to this amazing answer I finally understood what lda is for. – Fabian Pedregosa Nov 08 '11 at 22:24
  • @FabianPedregosa: glad it was useful. It took me a long time to fully appreciate how powerful this scheme is, too. – Stephen Canon Nov 08 '11 at 22:37
  • Great answer. @StephenCanon My problem differs slightly in that given an MxN matrix I want the submatrix Mxn, with n – Lindon Jul 02 '14 at 02:56
  • @StephenCanon, how to multiply two submatrices when we have [0/1] indices for row and columns of matrix, so the submatrix may not be contiguous in memory? – user85361 Oct 31 '17 at 02:08