larfb_gett(3)

๐Ÿ’… NAME ๐Ÿ’…

larfb_gett โ€” okay so this is a <pink>step in ungtsqr_row</pink>, bestie. That's the whole name section. Short and iconic. Also hi, this is the larfb_gett(3) page, manual name folded in nice and tidy like we promised โœจ


๐ŸŒธ SYNOPSIS ๐ŸŒธ

๐ŸŽ€ Functions

  • subroutine clarfb_gett (ident, m, n, k, t, ldt, a, lda, b, ldb, work, ldwork) โ€” CLARFB_GETT
  • subroutine dlarfb_gett (ident, m, n, k, t, ldt, a, lda, b, ldb, work, ldwork) โ€” DLARFB_GETT
  • subroutine slarfb_gett (ident, m, n, k, t, ldt, a, lda, b, ldb, work, ldwork) โ€” SLARFB_GETT
  • subroutine zlarfb_gett (ident, m, n, k, t, ldt, a, lda, b, ldb, work, ldwork) โ€” ZLARFB_GETT
Four flavors, same energy. Pick your precision, queen ๐Ÿ‘‘

๐Ÿฆ‹ Detailed Description ๐Ÿฆ‹

Lowkey this is where the actual lore lives โ€” keep scrolling for the Function Documentation and the details, because this page has SO much more coming (like, seven parts of more, we're just getting started ๐Ÿซถ).


๐Ÿ‘‘ Function Documentation ๐Ÿ‘‘

โญ subroutine clarfb_gett (character ident, integer m, integer n, integer k, complex, dimension( ldt, * ) t, integer ldt, complex, dimension( lda, * ) a, integer lda, complex, dimension( ldb, * ) b, integer ldb, complex, dimension( ldwork, * ) work, integer ldwork)

CLARFB_GETT

๐Ÿ’– Purpose:

!>
!> CLARFB_GETT applies a complex Householder block reflector H from the
!> left to a complex (K+M)-by-N   matrix
!> 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.
!>

So like โ€” CLARFB_GETT takes this complex Householder block reflector H and applies it from the left to a complex (K+M)-by-N matrix, which is literally two block matrices glued together: an upper trapezoidal K-by-N matrix A (living in the array A) and a rectangular M-by-(N-K) matrix B (living in the array B). The reflector H is stored in a compact WY-representation, with the elementary reflectors chillin' in A, B and T. The Further Details section has the receipts โœจ


๐ŸŒˆ 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.
!>

IDENT is a CHARACTER*1. If it's not 'I' or 'i', then V1 is unit lower-triangular and it IS stored in the left K-by-K block of the input matrix A. If IDENT is 'I' or 'i', then V1 is an identity matrix and it's simply not stored at all. The Further Details section knows more ๐Ÿ’…

  • M
!>          M is INTEGER
!>          The number of rows of the matrix B.
!>          M >= 0.
!>

M is INTEGER. It's the number of rows of matrix B. And M >= 0, no exceptions bestie.

  • N
!>          N is INTEGER
!>          The number of columns of the matrices A and B.
!>          N >= 0.
!>

N is INTEGER, the number of columns of the matrices A and B. Also N >= 0. Slay.

  • 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.
!>

K is INTEGER, the number of rows of matrix A. It's also the order of matrix T โ€” like, the number of elementary reflectors whose product defines the block reflector. Constraint: 0 <= K <= N. Periodt.

  • T
!>          T is COMPLEX array, dimension (LDT,K)
!>          The upper-triangular K-by-K matrix T in the representation
!>          of the block reflector.
!>

T is a COMPLEX array, dimension (LDT,K) โ€” the upper-triangular K-by-K matrix T in the block reflector representation ๐ŸŽ€

  • LDT
!>          LDT is INTEGER
!>          The leading dimension of the array T. LDT >= K.
!>

LDT is INTEGER, the leading dimension of array T. Respect the LDT >= K, fr fr.

  • A
!>          A is COMPLEX 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.
!>

A is a COMPLEX array, dimension (LDA,N). On entry you got two things goin' on: a) in the K-by-N upper-trapezoidal part A there's your input matrix A, and b) in the columns below the diagonal, the columns of V1 โ€” and no, the ones are not stored on the diagonal, iykyk. On exit, A gets overwritten by the rectangular K-by-N product H*A. Check the Further Details section for the full tea ๐ŸŒธ

  • LDA
!>          LDB is INTEGER
!>          The leading dimension of the array A. LDA >= max(1,K).
!>

LDA is INTEGER (yes, the page says LDB right here โ€” we are faithfully reporting, not judging ๐Ÿ™ˆ). It's the leading dimension of array A, and LDA >= max(1,K).

  • B
!>          B is COMPLEX 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.
!>

B is a COMPLEX array, dimension (LDB,N). On entry: a) in the M-by-(N-K) right block lives your input matrix B, and b) in the M-by-N left block, the columns of V2. On exit, B is overwritten by the rectangular M-by-N product H*B. Further Details section, as always ๐Ÿ’–

  • LDB
!>          LDB is INTEGER
!>          The leading dimension of the array B. LDB >= max(1,M).
!>

LDB is INTEGER, the leading dimension of array B, with LDB >= max(1,M). โœจ

  • WORK
!>          WORK is COMPLEX array,
!>          dimension (LDWORK,max(K,N-K))
!>

WORK is a COMPLEX array with dimension (LDWORK,max(K,N-K)). Do your thing, workspace ๐Ÿซถ

  • LDWORK
!>          LDWORK is INTEGER
!>          The leading dimension of the array WORK. LDWORK>=max(1,K).
!>
!>

LDWORK is INTEGER, the leading dimension of array WORK, and LDWORK>=max(1,K). That's the vibe check, passed ๐Ÿ”ฅ


๐Ÿ’œ 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
!>
!>

November 2020, Igor Kozachenko, Computer Science Division, University of California, Berkeley โ€” shoutout, icon ๐Ÿ‘‘


๐Ÿ“ Further Details:

hold that thought bestie, this is where part 1 hands off โ€” the details are literally right there in the next bit and we are NOT done yet ๐Ÿ’…

okay so this is the part where it gets mathematical ๐Ÿ’… but don't panic โ€” it's literally just "here's what's in the boxes, here's what comes out the other side." i gotchu.

๐Ÿ“ (1) Description of the Algebraic Operation

so. the matrix A is a K-by-N matrix made of two column blocks: A1, which is K-by-K, and A2, which is K-by-(N-K). like this:

A = ( A1, A2 ).

and the matrix B is an M-by-N matrix, also two column blocks: B1, which is M-by-K, and B2, which is M-by-(N-K). like this:

B = ( B1, B2 ).

here's the operation we're performing, no cap:

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

on input: โœจ

a) ( A_in ) over ( B_in ) consists of two block columns:

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

where the column blocks are:

  • ( A1_in ) is a K-by-K upper-triangular matrix stored in the upper triangular part of the array A(1:K,1:K).
  • ( B1_in ) is an M-by-K rectangular ZERO matrix and not stored.
  • ( A2_in ) is a K-by-(N-K) rectangular matrix stored in the array A(1:K,K+1:N).
  • ( B2_in ) is an M-by-(N-K) rectangular matrix stored in the array B(1:M,K+1:N).

b) V, which is built like this:

b) 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 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).

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

on output: ๐ŸŒธ

a) ( A_out ) over ( B_out ) consists of two block columns:

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

where the column blocks are:

  • ( A1_out ) is 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).
  • ( B1_out ) is an M-by-K rectangular matrix stored in the array B(1:M,K:N).
  • ( A2_out ) is a K-by-(N-K) rectangular matrix stored in the array A(1:K,K+1:N).
  • ( B2_out ) is 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, which is honestly so satisfying:

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

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

if IDENT != 'I':

the computation for column block 1:

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

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

the computation for column block 2, which exists if N > K:

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

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

if IDENT == 'I':

the operation for column block 1:

   A1_out: = A1_in - V1*T*A1_in

   B1_out: = - V2*T*A1_in

the computation for column block 2, which exists if N > K:

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

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

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

in the first step, we compute column block 2, i.e. A2 and B2. here, we need to use the K-by-(N-K) rectangular workspace matrix W2 that is of the same size as the matrix A2. W2 is stored in the array WORK(1:K,1:(N-K)).

in the second step, we compute column block 1, i.e. A1 and B1. here, we need to use the K-by-K square workspace matrix W1 that is of the same size as the as the matrix A1. W1 is stored 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.

case (A), when V1 is unit lower-triangular, i.e. IDENT != 'I', more computations than in the Case (B). ๐Ÿซถ

if( IDENT != 'I' ) then
 if ( N > K ) then
   (First Step - column block 2)
   col2_(1) W2: = A2
   col2_(2) W2: = (V1**H) * W2 = (unit_lower_tr_of_(A1)**H) * W2
   col2_(3) W2: = W2 + (V2**H) * B2 = W2 + (B1**H) * 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**H) * W1 = (unit_lower_tr_of_(A1)**H) * 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):

if( IDENT == 'I' ) then
 if ( N > K ) then
   (First Step - column block 2)
   col2_(1) W2: = A2
   col2_(3) W2: = W2 + (V2**H) * B2 = W2 + (B1**H) * 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, this is the resulting algorithm (she's iconic, she contains multitudes):

if ( N > K ) then

  (First Step - column block 2)

  col2_(1)  W2: = A2
  if( IDENT != 'I' ) then
    col2_(2)  W2: = (V1**H) * W2
                  = (unit_lower_tr_of_(A1)**H) * W2
  end if
  col2_(3)  W2: = W2 + (V2**H) * B2 = W2 + (B1**H) * 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**H) * W1
                = (unit_lower_tr_of_(A1)**H) * 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

okay and that's the whole vibe of the first version. Definition at line 390 of file clarfb_gett.f.


๐Ÿฆ‹ subroutine dlarfb_gett

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

DLARFB_GETT โ€” miss thing has arrived ๐Ÿ’…

Purpose

okay so, what does she even do:

DLARFB_GETT applies a real Householder block reflector H from the left to a real (K+M)-by-N matrix 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 the Further Details section โœจ

Parameters

  • 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 the Further Details section.
  • M โ€” is INTEGER. the number of rows of the matrix B. M >= 0.
  • N โ€” is INTEGER. the number of columns of the matrices A and B. N >= 0.
  • 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 โ€” a DOUBLE PRECISION array, dimension (LDT,K). This is the upper-triangular K-by-K matrix T living inside the representation of the block reflector. She's the triangle. She's iconic. ๐ŸŽ€
  • LDT โ€” INTEGER. The leading dimension of the array T, and the vibe check requires LDT >= K. no cap โœจ
  • A โ€” DOUBLE PRECISION array, dimension (LDA,N). Okay so this one has a whole before-and-after arc:

On entry, bestie:

  • a) In the K-by-N upper-trapezoidal part A: the input matrix A. Like, the actual data.
  • b) In the columns below the diagonal: the columns of V1 โ€” and heads up, the ones are not stored on the diagonal. they're implied. we stan an efficient queen ๐Ÿ’…

On exit:

  • A is overwritten by the rectangular K-by-N product H*A. rip original A, you had a good run ๐Ÿ˜ญ

See the Further Details section, iykyk.

  • LDA โ€” so the original page literally says LDB is INTEGER right here, and honestly? we're not fixing it, we're just reporting it ๐Ÿ™ˆ What it means is: this is INTEGER, the leading dimension of the array A, and LDA >= max(1,K). Periodt.
  • B โ€” DOUBLE PRECISION array, dimension (LDB,N). Same duality, different letter:

On entry:

  • a) In the M-by-(N-K) right block: the input matrix B.
  • b) In the M-by-N left block: the columns of V2.

On exit:

  • B is overwritten by the rectangular M-by-N product H*B. gone but not forgotten ๐Ÿฆ‹

See Further Details section again โ€” yes, both of them point there.

  • WORK โ€” DOUBLE PRECISION array, dimension (LDWORK,max(K,N-K)). It's the workspace. It's doing the behind-the-scenes labor and getting zero credit, main character energy tbh โญ
  • LDWORK โ€” INTEGER, the leading dimension of the array WORK, and the requirement is LDWORK>=max(1,K). don't skip it ๐Ÿ”ฅ

๐Ÿ‘‘ 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:

okay bestie the details go here โ€” next part, don't go anywhere ๐Ÿซถ

(1) Description of the Algebraic Operation ๐Ÿ’…

okay so bestie, picture the setup: A is a K-by-N matrix made of two column blocks โ€” A1 is K-by-K, and A2 is K-by-(N-K). So literally:

A = ( A1, A2 ).

And B is an M-by-N matrix made of two column blocks โ€” B1 is M-by-K, and B2 is M-by-(N-K):

B = ( B1, B2 ).

Then the operation being performed 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, ( A_in ) / ( B_in ) consists of two block columns:

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

where the column blocks are:

  • A1_in is a K-by-K upper-triangular matrix stored in the upper triangular part of A(1:K,1:K).
  • B1_in is an M-by-K rectangular ZERO matrix and not stored.
  • A2_in is a K-by-(N-K) rectangular matrix stored in A(1:K,K+1:N).
  • B2_in is an M-by-(N-K) rectangular matrix stored in B(1:M,K+1:N).

Then V is split like this:

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 A(1:K,1:K) (ones are not stored),

and V2 is an M-by-K rectangular matrix stored in 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.

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

On output, ( A_out ) / ( B_out ) consists of two block columns:

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

where the column blocks are:

  • A1_out is a K-by-K square matrix, or a K-by-K upper-triangular matrix if V1 is an identity matrix. AiOut is stored in A(1:K,1:K).
  • B1_out is an M-by-K rectangular matrix stored in B(1:M,K:N).
  • A2_out is a K-by-(N-K) rectangular matrix stored in A(1:K,K+1:N).
  • B2_out is an M-by-(N-K) rectangular matrix stored in 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

The computation for column block 2, which exists if N > K, is:

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', the operation for column block 1 is:

A1_out: = A1_in - V1*T**A1_in

B1_out: = - V2*T**A1_in

The computation for column block 2, which exists if N > K, is:

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 โœจ

In the first step, we compute column block 2, i.e. A2 and B2. Here, we need to use the K-by-(N-K) rectangular workspace matrix W2 that is of the same size as the matrix A2. W2 is stored in the array WORK(1:K,1:(N-K)).

In the second step, we compute column block 1, i.e. A1 and B1. Here, we need to use the K-by-K square workspace matrix W1 that is of the same size as the matrix A1. W1 is stored 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.

Case (A), when V1 is unit lower-triangular, i.e. IDENT != 'I', has more computations than in Case (B):

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', has less computations than in Case (A):

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:

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 dlarfb_gett.f.


subroutine slarfb_gett ๐ŸŒˆ

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 ๐Ÿ’–

SLARFB_GETT applies a real Householder block reflector H from the left to a real (K+M)-by-N matrix 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 of 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. rule of the land: LDT >= K. ๐ŸŽ€
  • A is a REAL array, dimension (LDA,N) ๐Ÿ’–

On entry, bestie:

a) In the K-by-N upper-trapezoidal part A: the input matrix A. (yes, that's the whole vibe)

b) In the columns below the diagonal: the columns of V1 โ€” and heads up, the ones are NOT stored on the diagonal ๐Ÿซถ

On exit: A gets overwritten by the rectangular K-by-N product H*A. ๐Ÿ’…

See the Further Details section (it's coming, don't worry).

  • LDA โ€” okay so real talk, the source page literally says LDB is INTEGER right here in this block, which is not a typo I made, that's just what's in the file ๐Ÿ˜ญ๐Ÿ™ˆ anyway: it's INTEGER, it's the leading dimension of the array A, and LDA >= max(1,K).
  • B is a REAL array, dimension (LDB,N) ๐Ÿฆ‹

On entry:

a) In the M-by-(N-K) right block: the input matrix B. โญ

b) In the M-by-N left block: the columns of V2. ๐ŸŒธ

On exit: B gets overwritten by the rectangular M-by-N product H*B. ๐Ÿ”ฅ

See Further Details โ€” same deal as above.

  • LDB is INTEGER โ€” the leading dimension of the array B. the bar is LDB >= max(1,M). no notes. ๐Ÿ’…
  • WORK is a REAL array, with dimension (LDWORK,max(K,N-K)) โœจ
  • LDWORK is INTEGER โ€” the leading dimension of the array WORK, and LDWORK>=max(1,K). ๐Ÿ‘‘

๐Ÿ‘‘ Author

Univ. of Tennessee

Univ. of California Berkeley

Univ. of Colorado Denver

NAG Ltd.

Not a group project you can ghost, fr fr. ๐Ÿซถ


๐Ÿงš Contributors

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

Absolute icon behaviour, we stan. ๐ŸŽ€


๐ŸŒˆ Further Details

๐Ÿ“ (1) Description of the Algebraic Operation

Okay so picture this. The matrix A is a K-by-N matrix built out of two column block matrices: A1, which is K-by-K, and A2, which is K-by-(N-K):

   A = ( A1, A2 ).

The matrix B is an M-by-N matrix, also built from two column block matrices: B1, which is M-by-K, and B2, which is M-by-(N-K):

   B = ( B1, B2 ).

Then we perform the operation:

      ( 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:

a) The stacked ( A_in ) / ( B_in ) situation consists of two block columns โœจ

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

where the column blocks are:

      (  A1_in )  is a K-by-K upper-triangular matrix stored in the
                  upper triangular part of the array A(1:K,1:K).
      (  B1_in )  is an M-by-K rectangular ZERO matrix and not stored.

      ( A2_in )  is a K-by-(N-K) rectangular matrix stored
                 in the array A(1:K,K+1:N).
      ( B2_in )  is an M-by-(N-K) rectangular matrix stored
                 in the array B(1:M,K+1:N).

b) The V situation ๐Ÿฆ‹

      V = ( V1 )
          ( V2 )

where:

  1. if IDENT == 'I', V1 is a K-by-K identity matrix, and it is 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 matrix stored in the array B(1:M,1:K) โ€” <lavender>(because on input B1_in is a rectangular zero matrix that is not stored and the space is used to store V2)</lavender>. Reusing the space, eco-friendly, we love to see it. โ™ป๏ธ๐Ÿ’…

c) T is a K-by-K upper-triangular matrix stored in the array T(1:K,1:K). โญ

On output:

a) The output stack also has two block columns:

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

where the column blocks are:

      ( A1_out )  is 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).
      ( B1_out )  is an M-by-K rectangular matrix stored
                  in the array B(1:M,K:N).

      ( A2_out )  is a K-by-(N-K) rectangular matrix stored
                  in the array A(1:K,K+1:N).
      ( B2_out )  is an M-by-(N-K) rectangular matrix stored
                  in the array B(1:M,K+1:N).

(yeah, AiOut and that B(1:M,K:N) are exactly what the page says โ€” I'm not touching them, that's above my pay grade ๐Ÿ™ˆ)

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:

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

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

The computation 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': ๐Ÿฆ‹

The operation for column block 1:

      A1_out: = A1_in - V1*T**A1_in

      B1_out: = - V2*T**A1_in

The computation for column block 2, which exists 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

In the first step, we compute column block 2, i.e. A2 and B2. Here, we need to use the K-by-(N-K) rectangular workspace matrix W2 that is of the same size as the matrix A2. W2 is stored in the array WORK(1:K,1:(N-K)). ๐Ÿ”ฅ

In the second step, we compute column block 1, i.e. A1 and B1. Here, we need to use the K-by-K square workspace matrix W1 that is of the same size as the as the matrix A1. W1 is stored in the array WORK(1:K,1:K). (yes, "as the as the" โ€” the source said it first, I'm just the messenger ๐Ÿ˜ญ)

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. One array, two jobs, main character energy. ๐Ÿ‘‘

Case (A), when V1 is unit lower-triangular, i.e. IDENT != 'I' โ€” more computations than in the Case (B). ๐Ÿ’…

    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). ๐Ÿฆ‹

    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 form ๐Ÿ’€๐Ÿ”ฅ:

    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

(and yeah, that stray ] on the col2_(3) line is coming straight from the source, we leave it be ๐Ÿซถ)

Definition at line 390 of file slarfb_gett.f. ๐ŸŽ€

๐Ÿซถ zlarfb_gett โ€” the complex*16 twin, aka the double-complex one ๐Ÿ’œ

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

ZLARFB_GETT โ€” that's the name, lowercase in the code, screaming in the docs, we love a versรกtil icon โœจ

๐Ÿ’– Purpose

Okay so bestie, here's the vibe: ZLARFB_GETT takes a complex Householder block reflector โ€” call her H โ€” and slaps her on the left side of a complex (K+M)-by-N matrix. And that big matrix? She's actually two block matrices glued together, main character energy ๐ŸŽ€:

  • an upper trapezoidal K-by-N matrix A, chilling in the array A, and
  • a rectangular M-by-(N-K) matrix B, chilling in the array B ๐Ÿฆ‹

The reflector H is stored in that compact WY-representation everyone keeps talking about, where the elementary reflectors live inside the arrays A, B and T. Not me being mysterious โ€” there's literally a Further Details section below, iykyk ๐Ÿ’…


๐ŸŒธ Parameters

  • IDENT โ€” IDENT is CHARACTER*1. Okay so this flag is doing a whole fork-in-the-road moment:
    • if IDENT = not 'I', or not 'i', then V1 is unit lower-triangular and it's 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 it is not stored at all, she's on vacation ๐Ÿ™ˆ
    • peep the Further Details section for the full lore ๐Ÿ’œ
  • M โ€” M is INTEGER. The number of rows of the matrix B. Constraint: M >= 0. Yes bestie, non-negative, we're not doing negative rows today ๐Ÿ’€
  • N โ€” N is INTEGER. The number of columns of the matrices A and B. Constraint: N >= 0. Same deal, zero is allowed, negative is not the vibe ๐ŸŒธ
  • K โ€” K is INTEGER, and honestly she's the busiest one here:
    • the number of rows of the matrix A (yes, the doc literally says "number or rows", we forgive her ๐Ÿ˜ญ)
    • also the order of the matrix T, meaning it's the number of elementary reflectors whose product defines the block reflector ๐Ÿ”ฅ
    • constraint: 0 <= K <= N โ€” keep it in that window, no cap โญ
  • T โ€” T is COMPLEX*16 array, dimension (LDT,K). This is the upper-triangular K-by-K matrix T in the representation of the block reflector. Queen of the WY-representation, literally ๐Ÿ‘‘
  • LDT โ€” LDT is INTEGER. The leading dimension of the array T. Constraint: LDT >= K. Don't skimp on the leading dimension, it's giving main character ๐ŸŽ€
  • A โ€” A is COMPLEX*16 array, dimension (LDA,N). Two whole personalities here:
    • On entry:
      • a) in the K-by-N upper-trapezoidal part A: the input matrix A ๐Ÿฆ‹
      • b) in the columns below the diagonal: the columns of V1 โ€” and heads up, the ones are not stored on the diagonal, they're implied, we're keeping it subtle ๐Ÿ™ˆ
    • On exit:
      • A is overwritten by the rectangular K-by-N product H*A ๐Ÿ”ฅ
    • see Further Details section, again, she keeps sending you there ๐Ÿ’…
  • LDA โ€” LDB is INTEGER. Yeah bestie, the original literally writes LDB in the LDA spot โ€” copy-paste moment, iconic, but it's talking about LDA, fr fr. The leading dimension of the array A. Constraint: LDA >= max(1,K) โœจ
  • B โ€” B is COMPLEX*16 array, dimension (LDB,N). Also dual-wielding:
    • On entry:
      • a) in the M-by-(N-K) right block: the input matrix B ๐ŸŒธ
      • b) in the M-by-N left block: the columns of V2 ๐Ÿซถ
    • On exit:
      • B is overwritten by the rectangular M-by-N product H*B ๐Ÿ”ฅ
    • Further Details section. She said what she said ๐Ÿ’œ
  • LDB โ€” LDB is INTEGER. The leading dimension of the array B. Constraint: LDB >= max(1,M) โญ
  • WORK โ€” WORK is COMPLEX*16 array, dimension (LDWORK,max(K,N-K)). This is the workspace, the backstage area where all the actual work happens while the big names take the credit ๐ŸŽ€
  • LDWORK โ€” LDWORK is INTEGER. The leading dimension of the array WORK. Constraint: LDWORK>=max(1,K). Give the workspace room to breathe, she deserves it ๐Ÿ’…

๐Ÿ‘‘ Author

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

Four whole institutions, the academic avengers, we stan ๐Ÿซถ

๐Ÿงš Contributors

  • November 2020, Igor Kozachenko, Computer Science Division, University of California, Berkeley ๐ŸŒˆ

Shoutout Igor, dropping this in November 2020, a whole era ๐Ÿ’œ


๐ŸŒŸ Further Details

Okay this is the part where she actually explains the WY-representation, so grab a snack ๐Ÿ“ โ€”

(1) Description of the Algebraic Operation ๐Ÿ’…

Okay bestie, matrix tea time โ˜•โœจ. The matrix A is a K-by-N matrix made of two column block matrices, A1 (that's K-by-K) and A2 (that's K-by-(N-K)):

A = ( A1, A2 ).

The matrix B is an M-by-N matrix made of two column block matrices, B1 (that's M-by-K) and B2 (that's M-by-(N-K)):

B = ( B1, B2 ).

Perform the operation:

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

On input:

a) ( A_in ) over ( B_in ) consists of two block columns:

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

where the column blocks are:

  • ( A1_in ) is a K-by-K upper-triangular matrix stored in the upper triangular part of the array A(1:K,1:K).
  • ( B1_in ) is an M-by-K rectangular ZERO matrix and not stored.
  • ( A2_in ) is a K-by-(N-K) rectangular matrix stored in the array A(1:K,K+1:N).
  • ( B2_in ) is an M-by-(N-K) rectangular matrix stored in the array B(1:M,K+1:N).

b)

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 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).

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

On output:

a) ( A_out ) over ( B_out ) consists of two block columns:

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

where the column blocks are:

  • ( A1_out ) is 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).
  • ( B1_out ) is an M-by-K rectangular matrix stored in the array B(1:M,K:N).
  • ( A2_out ) is a K-by-(N-K) rectangular matrix stored in the array A(1:K,K+1:N).
  • ( B2_out ) is 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**H ) * ( A1_in )
       ( B1_out )        (     0 )                          (     0 )

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

If IDENT != 'I':

The computation for column block 1:

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

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

The computation for column block 2, which exists if N > K:

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

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

If IDENT == 'I':

The operation for column block 1:

       A1_out: = A1_in - V1*T*A1_in

       B1_out: = - V2*T*A1_in

The computation for column block 2, which exists if N > K:

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

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

(2) Description of the Algorithmic Computation โœจ

In the first step, we compute column block 2, i.e. A2 and B2. Here, we need to use the K-by-(N-K) rectangular workspace matrix W2 that is of the same size as the matrix A2. W2 is stored in the array WORK(1:K,1:(N-K)).

In the second step, we compute column block 1, i.e. A1 and B1. Here, we need to use the K-by-K square workspace matrix W1 that is of the same size as the as the matrix A1. W1 is stored 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. ๐Ÿซถ

Case (A), when V1 is unit lower-triangular, i.e. IDENT != 'I', more computations than in the Case (B).

    if( IDENT != 'I' ) then
     if ( N > K ) then
       (First Step - column block 2)
       col2_(1) W2: = A2
       col2_(2) W2: = (V1**H) * W2 = (unit_lower_tr_of_(A1)**H) * W2
       col2_(3) W2: = W2 + (V2**H) * B2 = W2 + (B1**H) * 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**H) * W1 = (unit_lower_tr_of_(A1)**H) * 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)

    if( IDENT == 'I' ) then
     if ( N > K ) then
       (First Step - column block 2)
       col2_(1) W2: = A2
       col2_(3) W2: = W2 + (V2**H) * B2 = W2 + (B1**H) * 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, this is the resulting algorithm:

    if ( N > K ) then

      (First Step - column block 2)

      col2_(1)  W2: = A2
      if( IDENT != 'I' ) then
        col2_(2)  W2: = (V1**H) * W2
                      = (unit_lower_tr_of_(A1)**H) * W2
      end if
      col2_(3)  W2: = W2 + (V2**H) * B2 = W2 + (B1**H) * 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**H) * W1
                    = (unit_lower_tr_of_(A1)**H) * 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 zlarfb_gett.f.

Author ๐Ÿซถ

Generated automatically by Doxygen for LAPACK from the source code. The robots handled this one, no cap. ๐Ÿค–๐Ÿ’–


Footer check: LAPACK Version 3.12.0, page larfb_gett(3), and the date slot is whatever the official footer carries โ€” this excerpt didn't print one, so we're not inventing it. Periodt. ๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from