PSLARZB(l)

πŸ“¦ version 1.5, in ubuntu jammy

πŸ’… 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, only STOREV = 'R' and DIRECT = '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 in DESCA( DTYPE_ ) β€” the descriptor type. in this case, DTYPE_A = 1.
  • CTXT_A (global) β€” stored in DESCA( CTXT_ ) β€” the BLACS context handle, indicating the BLACS process grid A is distributed over. the context itself is global, but the handle (the integer value) may vary.
  • M_A (global) β€” stored in DESCA( M_ ) β€” the number of rows in the global array A.
  • N_A (global) β€” stored in DESCA( N_ ) β€” the number of columns in the global array A.
  • MB_A (global) β€” stored in DESCA( MB_ ) β€” the blocking factor used to distribute the rows of the array.
  • NB_A (global) β€” stored in DESCA( NB_ ) β€” the blocking factor used to distribute the columns of the array.
  • RSRC_A (global) β€” stored in DESCA( RSRC_ ) β€” the process row over which the first row of the array A is distributed.
  • CSRC_A (global) β€” stored in DESCA( CSRC_ ) β€” the process column over which the first column of the array A is distributed.
  • LLD_A (local) β€” stored in DESCA( 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': apply Q or Q**T from the Left; = 'R': apply Q or Q**T from the Right.
  • TRANS β€” (global input) CHARACTER. = 'N': No transpose, apply Q; = 'T': Transpose, apply Q**T.
  • DIRECT β€” (global input) CHARACTER. tells you how H is 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 submatrix sub( C ). M >= 0.
  • N β€” (global input) INTEGER. the number of columns to be operated on, i.e. the number of columns of the distributed submatrix sub( C ). N >= 0.
  • K β€” (global input) INTEGER. the order of the matrix T (= the number of elementary reflectors whose product defines the block reflector).
  • L β€” (global input) INTEGER. the columns of the distributed submatrix sub( A ) containing the meaningful part of the Householder reflectors. if SIDE = 'L', M >= L >= 0; if SIDE = 'R', N >= L >= 0.
  • V β€” (local input) REAL pointer into the local memory to an array of dimension (LLD_V, LOCc(JV+M-1)) if SIDE = 'L', (LLD_V, LOCc(JV+N-1)) if SIDE = 'R'. it holds the local pieces of the distributed vectors V representing the Householder transformation as returned by PSTZRZF. LLD_V >= LOCr(IV+K-1).
  • IV β€” (global input) INTEGER. the row index in the global array V indicating the first row of sub( V ).
  • JV β€” (global input) INTEGER. the column index in the global array V indicating the first column of sub( V ).
  • DESCV β€” (global and local input) INTEGER array of dimension DLEN_. the array descriptor for the distributed matrix V.
  • T β€” (local input) REAL array, dimension MB_V by MB_V. the lower triangular matrix T in the representation of the block reflector.
  • C β€” (local input/local output) REAL pointer into the local memory to an array of dimension (LLD_C,LOCc(JC+N-1)). on entry, the M-by-N distributed matrix sub( C ). on exit, sub( C ) is overwritten by Q*sub( C ) or Q'*sub( C ) or sub( C )*Q or sub( C )*Q'. she does not ask permission, she just overwrites. 😭
  • IC β€” (global input) INTEGER. the row index in the global array C indicating the first row of sub( C ).
  • JC β€” (global input) INTEGER. the column index in the global array C indicating the first column of sub( C ).
  • DESCC β€” (global and local input) INTEGER array of dimension DLEN_. the array descriptor for the distributed matrix C.
  • WORK β€” (local workspace) REAL array, 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