/home/abui...rfb_gett.f(3)
π ZLARFB_GETT β /home/abui...rfb_gett.f(3) π
okay bestie, this is the Library Functions Manual page for /home/abui...rfb_gett.f(3). Itβs giving βLAPACK source file but make it a whole mood.β π
No cap, every detail is staying.
β¨ NAME β¨
/home/abuild/rpmbuild/BUILD/lapack-static-3.12.0-build/lapack-3.12.0/SRC/zlarfb_gett.f
π SYNOPSIS π
π§ Functions/Subroutines π§
subroutine ZLARFB_GETT (ident, m, n, k, t, ldt, a, lda, b, ldb, work,
ldwork)
ZLARFB_GETT
π Function/Subroutine Documentation π
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 β yes, thatβs the whole name, and itβs iconic. π«Ά
π Purpose π
okay so ZLARFB_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. π
π Parameters π
IDENTβIDENTisCHARACTER*1. IfIDENT = not 'I', or not 'i', thenV1is unit lower-triangular and stored in the leftK-by-Kblock of the input matrixA. IfIDENT = 'I'or'i', thenV1is an identity matrix and not stored. See Further Details section.MβMisINTEGER; the number of rows of the matrixB.M >= 0.NβNisINTEGER; the number of columns of the matricesAandB.N >= 0.KβKisINTEGER; the number or rows of the matrixA.Kis also order of the matrixT, i.e. the number of elementary reflectors whose product defines the block reflector.0 <= K <= N.TβTisCOMPLEX*16array, dimension(LDT,K). The upper-triangularK-by-KmatrixTin the representation of the block reflector.LDTβLDTisINTEGER; the leading dimension of the arrayT.LDT >= K.AβAisCOMPLEX*16array, dimension(LDA,N).- On entry:
- a) In the
K-by-Nupper-trapezoidal partA: input matrixA. - b) In the columns below the diagonal: columns of
V1(ones are not stored on the diagonal).
- a) In the
- On exit:
Ais overwritten by rectangularK-by-NproductH*A.
- See Further Details section.
- On entry:
LDAβ the page literally saysLDB is INTEGERhere π; then: the leading dimension of the arrayA.LDA >= max(1,K).BβBisCOMPLEX*16array, dimension(LDB,N).- On entry:
- a) In the
M-by-(N-K)right block: input matrixB. - b) In the
M-by-Nleft block: columns ofV2.
- a) In the
- On exit:
Bis overwritten by rectangularM-by-NproductH*B.
- See Further Details section.
- On entry:
LDBβLDBisINTEGER; the leading dimension of the arrayB.LDB >= max(1,M).WORKβWORKisCOMPLEX*16array, dimension(LDWORK,max(K,N-K)).LDWORKβLDWORKisINTEGER; the leading dimension of the arrayWORK.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 πΈ
β¨ (the details section starts here β part 2 has the rest, bestie.) β¨
Okay so hereβs the math tea, bestie π
β this is the part where zlarfb_gett explains exactly what algebraic operation itβs doing, and honestly itβs giving βblock-matrix main character energy.β β¨
πΈ (1) Description of the Algebraic Operation πΈ
So A is a K-by-N matrix made of two column block matrices: A1, which is K-by-K, and A2, which is K-by-(N-K). The vibe is:
A = ( A1, A2 ).
And B is an M-by-N matrix made of two column block matrices: B1, which is M-by-K, and B2, which is M-by-(N-K). Same energy:
B = ( B1, B2 ).
The actual operation being performed is this iconic little number:
( 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 )
Now, on input, the stacked thing
( 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 aK-by-Kupper-triangular matrix stored in the upper triangular part of the arrayA(1:K,1:K).( B1_in )is anM-by-Krectangular ZERO matrix, and it is not stored.( A2_in )is aK-by-(N-K)rectangular matrix stored in the arrayA(1:K,K+1:N).( B2_in )is anM-by-(N-K)rectangular matrix stored in the arrayB(1:M,K+1:N).
Then for the V situation, we have:
V = ( V1 )
( V2 )
where:
- if
IDENT == 'I',V1is aK-by-Kidentity matrix, not stored; - if
IDENT != 'I',V1is aK-by-Kunit lower-triangular matrix, stored in the lower-triangular part of the arrayA(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). Thatβs because on input B1_in is a rectangular zero matrix that is not stored, and the space is used to store V2. Efficient, lowkey iconic π
.
And T is a K-by-K upper-triangular matrix stored in the array T(1:K,1:K).
Now, on output, the stacked
( 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 aK-by-Ksquare matrix, or aK-by-Kupper-triangular matrix ifV1is an identity matrix. The source literally calls this stored thingAiOut, and itβs stored in the arrayA(1:K,1:K).( B1_out )is anM-by-Krectangular matrix stored in the arrayB(1:M,K:N).( A2_out )is aK-by-(N-K)rectangular matrix stored in the arrayA(1:K,K+1:N).( B2_out )is anM-by-(N-K)rectangular matrix stored in the arrayB(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', then the computation for column block 1 is:
A1_out: = A1_in - V1*T*(V1**H)*A1_in
B1_out: = - V2*T*(V1**H)*A1_in
And the computation for column block 2, which exists if N > K, is:
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', then the operation for column block 1 is:
A1_out: = A1_in - V1*T*A1_in
B1_out: = - V2*T*A1_in
And the computation for column block 2, which exists if N > K, is:
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 matrix A1. W1 is stored in the array WORK(1:K,1:K).
NOTE: Hence, in this routine, we need the workspace arrayWORKonly of sizeWORK(1:K,1:max(K,N-K)), so it can hold bothW2from the first step andW1from the second step. Efficient use of space, we love to see it π«Ά.
Case (A) is when V1 is unit lower-triangular, i.e. IDENT != 'I' β 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**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) is when V1 is an identity matrix, i.e. IDENT == 'I' β 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**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, and this is the resulting algorithm β and yes, that stray ] after B2 in col2_(3) is literally in the source, bestie π leave it be:
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.
Thatβs the whole page, bestie β from LAPACK Version 3.12.0, page path /home/abui...rfb_gett.f(3) π«Άβ¨
π¦ where this page comes from
- opensuse-leap 16.0: lapack-man 3.12.0-160000.2.2 Β· BSD-3-Clause
- opensuse-leap 16.0: lapack-man 3.12.0-160000.2.2 Β· BSD-3-Clause
- opensuse-leap 16.0: lapack-man 3.12.0-160000.2.2 Β· BSD-3-Clause
- opensuse-leap 16.0: lapack-man 3.12.0-160000.2.2 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms