/home/abui...rfb_gett.f(3)

๐Ÿ“ฆ version 3.12.0, in opensuse-leap 16.0

๐ŸŽ€ SLARFB_GETT ๐ŸŽ€

Library Functions Manual โ€” /home/abui...rfb_gett.f(3)

โœจ NAME โœจ

okay so the NAME here is literally the source-file path, bestie: /home/abuild/rpmbuild/BUILD/lapack-static-3.12.0-build/lapack-3.12.0/SRC/slarfb_gett.f. Thatโ€™s the whole vibe. ๐Ÿ’…

๐ŸŒธ SYNOPSIS ๐ŸŒธ

๐Ÿงš Functions/Subroutines

subroutine SLARFB_GETT (ident, m, n, k, t, ldt, a, lda, b, ldb, work,
    ldwork)
    SLARFB_GETT

๐Ÿฆ‹ Function/Subroutine Documentation ๐Ÿฆ‹

subroutine SLARFB_GETT (character ident, integer m, integer n, integer k,
    real, dimension( ldt, * ) t, integer ldt, real, dimension( lda, * ) a,
    integer lda, real, dimension( ldb, * ) b, integer ldb, real, dimension(
    ldwork, * ) work, integer ldwork)

SLARFB_GETT

๐Ÿ’– Purpose

okay bestie, SLARFB_GETT applies a real Householder block reflector H from the left to a real (K+M)-by-N matrix. That matrix is composed of two block matrices: an upper trapezoidal K-by-N matrix A stored in the array A, and a rectangular M-by-(N-K) matrix B, stored in the array B. The block reflector H is stored in a compact WY-representation, where the elementary reflectors are in the arrays A, B and T. See Further Details section. โœจ

๐Ÿ’… Parameters

  • IDENT โ€” IDENT is CHARACTER*1.
    • If IDENT = not 'I', or not 'i', then V1 is unit lower-triangular and stored in the left K-by-K block of the input matrix A.
    • If IDENT = 'I' or 'i', then V1 is an identity matrix and not stored.
    • See Further Details section.
  • M โ€” M is INTEGER. The number of rows of the matrix B. M >= 0.
  • N โ€” N is INTEGER. The number of columns of the matrices A and B. N >= 0.
  • K โ€” K is INTEGER. The number or rows of the matrix A. K is also order of the matrix T, i.e. the number of elementary reflectors whose product defines the block reflector. 0 <= K <= N.
  • T โ€” T is REAL array, dimension (LDT,K). The upper-triangular K-by-K matrix T in the representation of the block reflector.
  • LDT โ€” LDT is INTEGER. The leading dimension of the array T. LDT >= K.
  • A โ€” A is REAL array, dimension (LDA,N).
    • On entry:
      • a) In the K-by-N upper-trapezoidal part A: input matrix A.
      • b) In the columns below the diagonal: columns of V1 (ones are not stored on the diagonal).
    • On exit:
      • A is overwritten by rectangular K-by-N product H*A.
    • See Further Details section.
  • LDA โ€” okay the page literally says LDB is INTEGER in this spot, so weโ€™re copying that exactly, no cap. The leading dimension of the array A. LDA >= max(1,K).
  • B โ€” B is REAL array, dimension (LDB,N).
    • On entry:
      • a) In the M-by-(N-K) right block: input matrix B.
      • b) In the M-by-N left block: columns of V2.
    • On exit:
      • B is overwritten by rectangular M-by-N product H*B.
    • See Further Details section.
  • LDB โ€” LDB is INTEGER. The leading dimension of the array B. LDB >= max(1,M).
  • WORK โ€” WORK is REAL array, dimension (LDWORK,max(K,N-K)).
  • LDWORK โ€” LDWORK is INTEGER. The leading dimension of the array WORK. LDWORK>=max(1,K).

๐Ÿ‘‘ Author

  • Univ. of Tennessee
  • Univ. of California Berkeley
  • Univ. of Colorado Denver
  • NAG Ltd.

๐ŸŒˆ Contributors

  • November 2020, Igor Kozachenko, Computer Science Division, University of California, Berkeley

๐Ÿฆ‹ Further Details

(1) Description of the Algebraic Operation โœจ

Okay so picture this, bestie: you've got a K-by-N matrix A that's actually two column blocks stitched together โ€” A1 (which is K-by-K) and A2 (which is K-by-(N-K)). Literally:

A = ( A1, A2 ).

Then there's an M-by-N matrix B, also two column blocks: B1 (M-by-K) and B2 (M-by-(N-K)). Like:

B = ( B1, B2 ).

Now the main character operation is:

   ( A_out ) := H * ( A_in ) = ( I - V * T * V**T ) * ( A_in ) =
   ( B_out )        ( B_in )                          ( B_in )
              = ( I - ( V1 ) * T * ( V1**T, V2**T ) ) * ( A_in )
                      ( V2 )                            ( B_in )

On input, the ( A_in ) over ( B_in ) situation has two block columns:

   ( A_in ) = (( A1_in ) ( A2_in )) = (( A1_in ) ( A2_in ))
   ( B_in )   (( B1_in ) ( B2_in ))   ((     0 ) ( B2_in )),

where each column block is:

  • ( A1_in ) โ€” a K-by-K upper-triangular matrix stored in the upper triangular part of the array A(1:K,1:K).
  • ( B1_in ) โ€” an M-by-K rectangular ZERO matrix and it's not even stored (because why store zeros, right?).
  • ( A2_in ) โ€” a K-by-(N-K) rectangular matrix stored in the array A(1:K,K+1:N).
  • ( B2_in ) โ€” an M-by-(N-K) rectangular matrix stored in the array B(1:M,K+1:N).

Then there's V, which is:

V = ( V1 )
    ( V2 )

where:

  1. if IDENT == 'I', V1 is a K-by-K identity matrix, not stored;
  2. if IDENT != 'I', V1 is a K-by-K unit lower-triangular matrix, stored in the lower-triangular part of the array A(1:K,1:K) (ones are not stored), and V2 is an M-by-K rectangular stored in the array B(1:M,1:K), (because on input B1_in is a rectangular zero matrix that is not stored and the space is used to store V2).

Then T is a K-by-K upper-triangular matrix stored in the array T(1:K,1:K).

On output, the ( A_out ) over ( B_out ) has two block columns:

   ( A_out ) = (( A1_out ) ( A2_out ))
   ( B_out )   (( B1_out ) ( B2_out )),

where:

  • ( A1_out ) โ€” a K-by-K square matrix, or a K-by-K upper-triangular matrix, if V1 is an identity matrix. AiOut is stored in the array A(1:K,1:K). (Yes, AiOut โ€” that's what it says, bestie.)
  • ( B1_out ) โ€” an M-by-K rectangular matrix stored in the array B(1:M,K:N).
  • ( A2_out ) โ€” a K-by-(N-K) rectangular matrix stored in the array A(1:K,K+1:N).
  • ( B2_out ) โ€” an M-by-(N-K) rectangular matrix stored in the array B(1:M,K+1:N).

The operation above can be represented as the same operation on each block column:

   ( A1_out ) := H * ( A1_in ) = ( I - V * T * V**T ) * ( A1_in )
   ( B1_out )        (     0 )                          (     0 )

   ( A2_out ) := H * ( A2_in ) = ( I - V * T * V**T ) * ( A2_in )
   ( B2_out )        ( B2_in )                          ( B2_in )

If IDENT != 'I', the computation for column block 1 is:

   A1_out: = A1_in - V1*T*(V1**T)*A1_in

   B1_out: = - V2*T*(V1**T)*A1_in

And for column block 2 (which exists if N > K):

   A2_out: = A2_in - V1*T*( (V1**T)*A2_in + (V2**T)*B2_in )

   B2_out: = B2_in - V2*T*( (V1**T)*A2_in + (V2**T)*B2_in )

If IDENT == 'I', column block 1 is:

   A1_out: = A1_in - V1*T**A1_in

   B1_out: = - V2*T**A1_in

And column block 2 (again, only if N > K):

   A2_out: = A2_in - T*( A2_in + (V2**T)*B2_in )

   B2_out: = B2_in - V2*T*( A2_in + (V2**T)*B2_in )

(2) Description of the Algorithmic Computation ๐Ÿงฎ

First step: compute column block 2 (so A2 and B2). For that you need a K-by-(N-K) rectangular workspace matrix W2 that's the same size as A2. W2 lives in the array WORK(1:K,1:(N-K)).

Second step: compute column block 1 (A1 and B1). This needs a K-by-K square workspace matrix W1 that's the same size as the matrix A1. W1 lives in the array WORK(1:K,1:K).

NOTE: Hence, in this routine, we need the workspace array WORK only of size WORK(1:K,1:max(K,N-K)) so it can hold both W2 from the first step and W1 from the second step. Slay, efficient queen.

Case (A), when V1 is unit lower-triangular, i.e. IDENT != 'I' โ€” more computations than in the Case (B). Here's the pseudocode:

if( IDENT != 'I' ) then
 if ( N > K ) then
   (First Step - column block 2)
   col2_(1) W2: = A2
   col2_(2) W2: = (V1**T) * W2 = (unit_lower_tr_of_(A1)**T) * W2
   col2_(3) W2: = W2 + (V2**T) * B2 = W2 + (B1**T) * B2
   col2_(4) W2: = T * W2
   col2_(5) B2: = B2 - V2 * W2 = B2 - B1 * W2
   col2_(6) W2: = V1 * W2 = unit_lower_tr_of_(A1) * W2
   col2_(7) A2: = A2 - W2
 else
   (Second Step - column block 1)
   col1_(1) W1: = A1
   col1_(2) W1: = (V1**T) * W1 = (unit_lower_tr_of_(A1)**T) * W1
   col1_(3) W1: = T * W1
   col1_(4) B1: = - V2 * W1 = - B1 * W1
   col1_(5) square W1: = V1 * W1 = unit_lower_tr_of_(A1) * W1
   col1_(6) square A1: = A1 - W1
 end if
end if

Case (B), when V1 is an identity matrix, i.e. IDENT == 'I' โ€” less computations than in the Case (A). Because we love a shortcut:

if( IDENT == 'I' ) then
 if ( N > K ) then
   (First Step - column block 2)
   col2_(1) W2: = A2
   col2_(3) W2: = W2 + (V2**T) * B2 = W2 + (B1**T) * B2
   col2_(4) W2: = T * W2
   col2_(5) B2: = B2 - V2 * W2 = B2 - B1 * W2
   col2_(7) A2: = A2 - W2
 else
   (Second Step - column block 1)
   col1_(1) W1: = A1
   col1_(3) W1: = T * W1
   col1_(4) B1: = - V2 * W1 = - B1 * W1
   col1_(6) upper-triangular_of_(A1): = A1 - W1
 end if
end if

Combine these cases (A) and (B) together, and this is the resulting algorithm โ€” the final boss:

if ( N > K ) then

  (First Step - column block 2)

  col2_(1)  W2: = A2
  if( IDENT != 'I' ) then
    col2_(2)  W2: = (V1**T) * W2
                  = (unit_lower_tr_of_(A1)**T) * W2
  end if
  col2_(3)  W2: = W2 + (V2**T) * B2 = W2 + (B1**T) * B2]
  col2_(4)  W2: = T * W2
  col2_(5)  B2: = B2 - V2 * W2 = B2 - B1 * W2
  if( IDENT != 'I' ) then
    col2_(6)    W2: = V1 * W2 = unit_lower_tr_of_(A1) * W2
  end if
  col2_(7) A2: = A2 - W2

else

(Second Step - column block 1)

  col1_(1) W1: = A1
  if( IDENT != 'I' ) then
    col1_(2) W1: = (V1**T) * W1
                = (unit_lower_tr_of_(A1)**T) * W1
  end if
  col1_(3) W1: = T * W1
  col1_(4) B1: = - V2 * W1 = - B1 * W1
  if( IDENT != 'I' ) then
    col1_(5) square W1: = V1 * W1 = unit_lower_tr_of_(A1) * W1
    col1_(6_a) below_diag_of_(A1): =  - below_diag_of_(W1)
  end if
  col1_(6_b) up_tr_of_(A1): = up_tr_of_(A1) - up_tr_of_(W1)

end if

Definition at line 390 of file slarfb_gett.f.


Author ๐Ÿ‘‘

Generated automatically by Doxygen for LAPACK from the source code.


And that's the whole vibe, bestie! This iconic page was brought to you by LAPACK Version 3.12.0 straight from the source file /home/abui...rfb_gett.f(3) โ€” no cap, it's giving documentation realness. Stay slay! ๐Ÿ’…โœจ๐ŸŽ€

๐Ÿ“ฆ where this page comes from