0

Introduction:

I'm using the Intel Math Kernel Library (MKL) functions LAPACKE_dgeqrf and LAPACKE_dorgqr for generating the QR decomposition of a general input matrix A of size (m x n) stored in row-major order, (where m is the number of A's rows and n is the number of A's columns).

Below is the code I use:

C++ Code:

void qr (double *Q, double *R, double *A, const size_t m, const size_t n) {
    std::size_t k = std::max(std::size_t(1), std::min(m, n)); // The number of elementary reflectors

    std::unique_ptr<double[]> tau(new double[k]); // Scalars that define elementary reflectors

    LAPACKE_dgeqrf(LAPACK_ROW_MAJOR, m, n, A, n, tau.get());

    // Generate R matrix
    for (std::size_t i(0); i < n; ++i) {
        std::memset(R + i * n    , 0            , i       * sizeof(double));
        std::memcpy(R + i * n + i, A + i * n + i, (n - i) * sizeof(double));
    }

    // Generate Q matrix
    LAPACKE_dorgqr(LAPACK_ROW_MAJOR, m, k, k, A, n, tau.get());

    if(m == n) {
        std::memcpy(Q, A, sizeof(double) * (m * m));
    } else {
        for(std::size_t i(0); i < m; ++i) {
            std::memcpy(Q + i * k, A + i * n, sizeof(double) * (k));
        }
    }
}

Related Info:

The code above is a slightly refactored version of the code I found in another related answer to a similar question.

https://stackoverflow.com/a/29408035/2352671

Description:

  • LAPACKE_dgeqrf overwrites on the upper triangular part of input matrix A, the upper triangular part of (mxn) upper triangular matrix R. So matrix R can be easily extracted as shown in the code.
  • The lower triangular part of the overwritten matrix, A, holds information about the Householder transformations.
  • In array tau the scalar factors of the elementary reflectors used in the Householder transformations are stored.
  • In order to extract matrix Q from the above given information, we use LAPACKE_dorgqr.
  • LAPACKE_dorgqr seems to work well for input matrices where (m ≤ n) (i.e., the number of rows of input matrix A is less than or equal to the number of its columns). That is, when (m == n), LAPACKE_dorgqr overwrites on input matrix A, which as shown is the result of LAPACKE_dgeqrf, (mxm) matrix Q. When (m < n) first m columns of overwritten matrix A represent (mxm) matrix Q. So in these cases as illustrated in the code, Q can be easily extracted.
  • However, in the case where (m > n) (i.e., the number of rows of input matrix A is greater than the number of its columns), LAPACKE_dorgqr outputs only the first n columns of matrix Q.

Questions:

  • How to generate the rest of the missing columns of Q in the case where the input matrix's rows are greater than the number of its columns?
  • Am I missing something? That is, am I misusing the API?
  • Is this API's normal behavior, and I've to generate the rest of the column orthogonal vectors of matrix Q using some generation process like Gram–Schmidt from the existing orthogonal column vectors?
  • Do I have to solve a system for obtaining the full matrix Q, since I have matrix R?
101010
  • 41,839
  • 11
  • 94
  • 168
  • 1
    As mentioned, You can generate the missing columns of Q using the Gram-Schmidt process on the remaining columns of A. You are not misusing the API as the LAPACKE_dorgqr behaves as intended in generating the orthogonal matrix Q based on the number of columns of the input matrix A. Yes, you can use the Gram-Schmidt process to generate the missing columns of Q. – Shanmukh-Intel Aug 28 '23 at 18:23
  • @Shanmukh-Intel I solved the problem via padding zero filled columns, so that input matrix A becomes a square matrix. Is this correct? – 101010 Aug 29 '23 at 14:19

0 Answers0