PSLARZB(l)
π PSLARZB β LAPACK auxiliary routine (version 1.5) π
okay bestie, gather round, because today we are learning about PSLARZB, a LAPACK auxiliary routine that is lowkey doing the most and deserves its flowers. π
β¨ NAME β¨
PSLARZB β applies a real block reflector Q or its transpose Q**T to a real distributed M-by-N matrix sub( C ) = C(IC:IC+M-1,JC:JC+N-1). yes that's the whole job. she's focused. π
πΈ SYNOPSIS πΈ
SUBROUTINE PSLARZB( SIDE, TRANS, DIRECT, STOREV, M, N, K, L, V, IV, JV,
DESCV, T, C, IC, JC, DESCC, WORK )
CHARACTER DIRECT, SIDE, STOREV, TRANS
INTEGER IC, IV, JC, JV, K, L, M, N
INTEGER DESCC( * ), DESCV( * )
REAL C( * ), T( * ), V( * ), WORK( * )
π PURPOSE π
PSLARZB applies a real block reflector Q or its transpose Q**T to a real distributed M-by-N matrix sub( C ) = C(IC:IC+M-1,JC:JC+N-1), from the left or from the right. pick a side, she'll serve. π«Ά
Q is a product of k elementary reflectors, exactly as returned by PSTZRZF.
rn, onlySTOREV = 'R'andDIRECT = 'B'are supported. the other combos are giving "coming soon" energy, not "working code" energy. π
π Notes π
every global data object has a little bestie attached to it called a description vector. that vector holds everything needed to map an element of the object to its process and its memory location. no cap.
let A be a generic term for any 2D block cyclicly distributed array. such a global array has an associated description vector DESCA. in the comments below, read the character _ as "of the global array".
the notation, where it's stored, and what it means:
DTYPE_A(global) β stored inDESCA( DTYPE_ )β the descriptor type. in this case,DTYPE_A = 1.CTXT_A(global) β stored inDESCA( CTXT_ )β the BLACS context handle, indicating the BLACS process gridAis distributed over. the context itself is global, but the handle (the integer value) may vary.M_A(global) β stored inDESCA( M_ )β the number of rows in the global arrayA.N_A(global) β stored inDESCA( N_ )β the number of columns in the global arrayA.MB_A(global) β stored inDESCA( MB_ )β the blocking factor used to distribute the rows of the array.NB_A(global) β stored inDESCA( NB_ )β the blocking factor used to distribute the columns of the array.RSRC_A(global) β stored inDESCA( RSRC_ )β the process row over which the first row of the arrayAis distributed.CSRC_A(global) β stored inDESCA( CSRC_ )β the process column over which the first column of the arrayAis distributed.LLD_A(local) β stored inDESCA( LLD_ )β the leading dimension of the local array.LLD_A >= MAX(1,LOCr(M_A)).
let K be the number of rows or columns of a distributed matrix, and assume its process grid has dimension p x q.
LOCr( K ) is the number of elements of K that a process would receive if K were distributed over the p processes of its process column.
same vibe for LOCc( K ) β the number of elements of K a process would receive if K were distributed over the q processes of its process row.
you can get LOCr() and LOCc() by calling the ScaLAPACK tool function NUMROC:
LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
and an upper bound for those quantities can be computed like:
LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
π ARGUMENTS π
SIDEβ (global input)CHARACTER.= 'L': applyQorQ**Tfrom the Left;= 'R': applyQorQ**Tfrom the Right.TRANSβ (global input)CHARACTER.= 'N': No transpose, applyQ;= 'T': Transpose, applyQ**T.DIRECTβ (global input)CHARACTER. tells you howHis formed from a product of elementary reflectors.= 'F':H = H(1) H(2) . . . H(k)(Forward, not supported yet);= 'B':H = H(k) . . . H(2) H(1)(Backward).STOREVβ (global input)CHARACTER. tells you how the vectors that define the elementary reflectors are stored:= 'C': Columnwise (not supported yet);= 'R': Rowwise.Mβ (global input)INTEGER. the number of rows to be operated on, i.e. the number of rows of the distributed submatrixsub( C ).M >= 0.Nβ (global input)INTEGER. the number of columns to be operated on, i.e. the number of columns of the distributed submatrixsub( C ).N >= 0.Kβ (global input)INTEGER. the order of the matrixT(= the number of elementary reflectors whose product defines the block reflector).Lβ (global input)INTEGER. the columns of the distributed submatrixsub( A )containing the meaningful part of the Householder reflectors. ifSIDE = 'L',M >= L >= 0; ifSIDE = 'R',N >= L >= 0.Vβ (local input)REALpointer into the local memory to an array of dimension(LLD_V, LOCc(JV+M-1))ifSIDE = 'L',(LLD_V, LOCc(JV+N-1))ifSIDE = 'R'. it holds the local pieces of the distributed vectorsVrepresenting the Householder transformation as returned byPSTZRZF.LLD_V >= LOCr(IV+K-1).IVβ (global input)INTEGER. the row index in the global arrayVindicating the first row ofsub( V ).JVβ (global input)INTEGER. the column index in the global arrayVindicating the first column ofsub( V ).DESCVβ (global and local input)INTEGERarray of dimensionDLEN_. the array descriptor for the distributed matrixV.Tβ (local input)REALarray, dimensionMB_VbyMB_V. the lower triangular matrixTin the representation of the block reflector.Cβ (local input/local output)REALpointer into the local memory to an array of dimension(LLD_C,LOCc(JC+N-1)). on entry, theM-by-Ndistributed matrixsub( C ). on exit,sub( C )is overwritten byQ*sub( C )orQ'*sub( C )orsub( C )*Qorsub( C )*Q'. she does not ask permission, she just overwrites. πICβ (global input)INTEGER. the row index in the global arrayCindicating the first row ofsub( C ).JCβ (global input)INTEGER. the column index in the global arrayCindicating the first column ofsub( C ).DESCCβ (global and local input)INTEGERarray of dimensionDLEN_. the array descriptor for the distributed matrixC.WORKβ (local workspace)REALarray, dimension(LWORK). and now, the iconic nested-if moment:
if STOREV = 'C', if SIDE = 'L', LWORK >= ( NqC0 + MpC0 ) * K else if SIDE = 'R', LWORK >= ( NqC0 + MAX( NpV0 + NUMROC( NUMROC( N+ICOFFC, NB_V, 0, 0, NPCOL ), NB_V, 0, 0, LCMQ ), MpC0 ) ) * K end if else if STOREV = 'R', if SIDE = 'L', LWORK >= ( MpC0 + MAX( MqV0 + NUMROC( NUMROC( M+IROFFC, MB_V, 0, 0, NPROW ), MB_V, 0, 0, LCMP ), NqC0 ) ) * K else if SIDE = 'R', LWORK >= ( MpC0 + NqC0 ) * K end if end if
where:
LCMQ = LCM / NPCOL with LCM = ICLM( NPROW, NPCOL ),
IROFFV = MOD( IV-1, MB_V ), ICOFFV = MOD( JV-1, NB_V ), IVROW =
INDXG2P( IV, MB_V, MYROW, RSRC_V, NPROW ), IVCOL = INDXG2P( JV,
NB_V, MYCOL, CSRC_V, NPCOL ), MqV0 = NUMROC( M+ICOFFV, NB_V,
MYCOL, IVCOL, NPCOL ), NpV0 = NUMROC( N+IROFFV, MB_V, MYROW,
IVROW, NPROW ),
IROFFC = MOD( IC-1, MB_C ), ICOFFC = MOD( JC-1, NB_C ), ICROW =
INDXG2P( IC, MB_C, MYROW, RSRC_C, NPROW ), ICCOL = INDXG2P( JC,
NB_C, MYCOL, CSRC_C, NPCOL ), MpC0 = NUMROC( M+IROFFC, MB_C,
MYROW, ICROW, NPROW ), NpC0 = NUMROC( N+ICOFFC, MB_C, MYROW,
ICROW, NPROW ), NqC0 = NUMROC( N+ICOFFC, NB_C, MYCOL, ICCOL,
NPCOL ),
ILCM, INDXG2P and NUMROC are ScaLAPACK tool functions; MYROW, MYCOL, NPROW and NPCOL can be determined by calling the subroutine BLACS_GRIDINFO.
π§ Alignment requirements π§
the distributed submatrices V(IV:*, JV:*) and C(IC:IC+M-1,JC:JC+N-1) must verify some alignment properties, namely the following expressions should be true:
if STOREV = 'Columnwise', if SIDE = 'Left', ( MB_V.EQ.MB_C .AND. IROFFV.EQ.IROFFC .AND. IVROW.EQ.ICROW ); if SIDE = 'Right', ( MB_V.EQ.NB_C .AND. IROFFV.EQ.ICOFFC ); else if STOREV = 'Rowwise', if SIDE = 'Left', ( NB_V.EQ.MB_C .AND. ICOFFV.EQ.IROFFC ); if SIDE = 'Right', ( NB_V.EQ.NB_C .AND. ICOFFV.EQ.ICOFFC .AND. IVCOL.EQ.ICCOL ) end if.
and that's the whole page bestie, every flag, every formula, every NUMROC call, preserved with love. β¨
this iconic little writeup comes from LAPACK version 1.5, dated 12 May 1997 β an absolute elder of the distributed linear algebra game, and she still ate. π π no cap, periodt. π
π¦ where this page comes from
- ubuntu jammy: scalapack-doc 1.5-11
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms