LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ zlarft()

recursive subroutine zlarft ( character direct,
character storev,
integer n,
integer k,
complex*16, dimension( ldv, * ) v,
integer ldv,
complex*16, dimension( * ) tau,
complex*16, dimension( ldt, * ) t,
integer ldt )

ZLARFT forms the triangular factor T of a block reflector H = I - vtvH

Download ZLARFT + dependencies [TGZ] [ZIP] [TXT]

Purpose:
!>
!> ZLARFT forms the triangular factor T of a complex block reflector H
!> of order n, which is defined as a product of k elementary reflectors.
!>
!> If DIRECT = 'F', H = H(1) H(2) . . . H(k) and T is upper triangular;
!>
!> If DIRECT = 'B', H = H(k) . . . H(2) H(1) and T is lower triangular.
!>
!> If STOREV = 'C', the vector which defines the elementary reflector
!> H(i) is stored in the i-th column of the array V, and
!>
!>    H  =  I - V * T * V**H
!>
!> If STOREV = 'R', the vector which defines the elementary reflector
!> H(i) is stored in the i-th row of the array V, and
!>
!>    H  =  I - V**H * T * V
!> 
Parameters
[in]DIRECT
!>          DIRECT is CHARACTER*1
!>          Specifies the order in which the elementary reflectors are
!>          multiplied to form the block reflector:
!>          = 'F': H = H(1) H(2) . . . H(k) (Forward)
!>          = 'B': H = H(k) . . . H(2) H(1) (Backward)
!> 
[in]STOREV
!>          STOREV is CHARACTER*1
!>          Specifies how the vectors which define the elementary
!>          reflectors are stored (see also Further Details):
!>          = 'C': columnwise
!>          = 'R': rowwise
!> 
[in]N
!>          N is INTEGER
!>          The order of the block reflector H. N >= 0.
!> 
[in]K
!>          K is INTEGER
!>          The order of the triangular factor T (= the number of
!>          elementary reflectors). K >= 1.
!> 
[in]V
!>          V is COMPLEX*16 array, dimension
!>                               (LDV,K) if STOREV = 'C'
!>                               (LDV,N) if STOREV = 'R'
!>          The matrix V. See further details.
!> 
[in]LDV
!>          LDV is INTEGER
!>          The leading dimension of the array V.
!>          If STOREV = 'C', LDV >= max(1,N); if STOREV = 'R', LDV >= K.
!> 
[in]TAU
!>          TAU is COMPLEX*16 array, dimension (K)
!>          TAU(i) must contain the scalar factor of the elementary
!>          reflector H(i).
!> 
[out]T
!>          T is COMPLEX*16 array, dimension (LDT,K)
!>          The k by k triangular factor T of the block reflector.
!>          If DIRECT = 'F', T is upper triangular; if DIRECT = 'B', T is
!>          lower triangular. The rest of the array is not used.
!> 
[in]LDT
!>          LDT is INTEGER
!>          The leading dimension of the array T. LDT >= K.
!> 
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
Further Details:
!>
!>  The shape of the matrix V and the storage of the vectors which define
!>  the H(i) is best illustrated by the following example with n = 5 and
!>  k = 3. The elements equal to 1 are not stored.
!>
!>  DIRECT = 'F' and STOREV = 'C':         DIRECT = 'F' and STOREV = 'R':
!>
!>               V = (  1       )                 V = (  1 v1 v1 v1 v1 )
!>                   ( v1  1    )                     (     1 v2 v2 v2 )
!>                   ( v1 v2  1 )                     (        1 v3 v3 )
!>                   ( v1 v2 v3 )
!>                   ( v1 v2 v3 )
!>
!>  DIRECT = 'B' and STOREV = 'C':         DIRECT = 'B' and STOREV = 'R':
!>
!>               V = ( v1 v2 v3 )                 V = ( v1 v1  1       )
!>                   ( v1 v2 v3 )                     ( v2 v2 v2  1    )
!>                   (  1 v2 v3 )                     ( v3 v3 v3 v3  1 )
!>                   (     1 v3 )
!>                   (        1 )
!> 

Definition at line 160 of file zlarft.f.

162*
163* -- LAPACK auxiliary routine --
164* -- LAPACK is a software package provided by Univ. of Tennessee, --
165* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
166*
167* .. Scalar Arguments
168*
169 CHARACTER DIRECT, STOREV
170 INTEGER K, LDT, LDV, N
171* ..
172* .. Array Arguments ..
173*
174 COMPLEX*16 T( LDT, * ), TAU( * ), V( LDV, * )
175* ..
176*
177* .. Parameters ..
178*
179 COMPLEX*16 ONE, NEG_ONE, ZERO
180 parameter(one=1.0d+0, zero = 0.0d+0, neg_one=-1.0d+0)
181*
182* .. Local Scalars ..
183*
184 INTEGER I,J,L
185 LOGICAL QR,LQ,QL,DIRF,COLV
186*
187* .. External Subroutines ..
188*
189 EXTERNAL ztrmm,zgemm,zlacpy
190*
191* .. External Functions..
192*
193 LOGICAL LSAME
194 EXTERNAL lsame
195*
196* .. Intrinsic Functions..
197*
198 INTRINSIC conjg
199*
200* The general scheme used is inspired by the approach inside DGEQRT3
201* which was (at the time of writing this code):
202* Based on the algorithm of Elmroth and Gustavson,
203* IBM J. Res. Develop. Vol 44 No. 4 July 2000.
204* ..
205* .. Executable Statements ..
206*
207* Quick return if possible
208*
209 IF(n.EQ.0.OR.k.EQ.0) THEN
210 RETURN
211 END IF
212*
213* Base case
214*
215 IF(n.EQ.1.OR.k.EQ.1) THEN
216 t(1,1) = tau(1)
217 RETURN
218 END IF
219*
220* Beginning of executable statements
221*
222 l = k / 2
223*
224* Determine what kind of Q we need to compute
225* We assume that if the user doesn't provide 'F' for DIRECT,
226* then they meant to provide 'B' and if they don't provide
227* 'C' for STOREV, then they meant to provide 'R'
228*
229 dirf = lsame(direct,'F')
230 colv = lsame(storev,'C')
231*
232* QR happens when we have forward direction in column storage
233*
234 qr = dirf.AND.colv
235*
236* LQ happens when we have forward direction in row storage
237*
238 lq = dirf.AND.(.NOT.colv)
239*
240* QL happens when we have backward direction in column storage
241*
242 ql = (.NOT.dirf).AND.colv
243*
244* The last case is RQ. Due to how we structured this, if the
245* above 3 are false, then RQ must be true, so we never store
246* this
247* RQ happens when we have backward direction in row storage
248* RQ = (.NOT.DIRF).AND.(.NOT.COLV)
249*
250 IF(qr) THEN
251*
252* Break V apart into 6 components
253*
254* V = |---------------|
255* |V_{1,1} 0 |
256* |V_{2,1} V_{2,2}|
257* |V_{3,1} V_{3,2}|
258* |---------------|
259*
260* V_{1,1}\in\C^{l,l} unit lower triangular
261* V_{2,1}\in\C^{k-l,l} rectangular
262* V_{3,1}\in\C^{n-k,l} rectangular
263*
264* V_{2,2}\in\C^{k-l,k-l} unit lower triangular
265* V_{3,2}\in\C^{n-k,k-l} rectangular
266*
267* We will construct the T matrix
268* T = |---------------|
269* |T_{1,1} T_{1,2}|
270* |0 T_{2,2}|
271* |---------------|
272*
273* T is the triangular factor obtained from block reflectors.
274* To motivate the structure, assume we have already computed T_{1,1}
275* and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
276*
277* T_{1,1}\in\C^{l, l} upper triangular
278* T_{2,2}\in\C^{k-l, k-l} upper triangular
279* T_{1,2}\in\C^{l, k-l} rectangular
280*
281* Where l = floor(k/2)
282*
283* Then, consider the product:
284*
285* (I - V_1*T_{1,1}*V_1')*(I - V_2*T_{2,2}*V_2')
286* = I - V_1*T_{1,1}*V_1' - V_2*T_{2,2}*V_2' + V_1*T_{1,1}*V_1'*V_2*T_{2,2}*V_2'
287*
288* Define T_{1,2} = -T_{1,1}*V_1'*V_2*T_{2,2}
289*
290* Then, we can define the matrix V as
291* V = |-------|
292* |V_1 V_2|
293* |-------|
294*
295* So, our product is equivalent to the matrix product
296* I - V*T*V'
297* This means, we can compute T_{1,1} and T_{2,2}, then use this information
298* to compute T_{1,2}
299*
300* Compute T_{1,1} recursively
301*
302 CALL zlarft(direct, storev, n, l, v, ldv, tau, t, ldt)
303*
304* Compute T_{2,2} recursively
305*
306 CALL zlarft(direct, storev, n-l, k-l, v(l+1, l+1), ldv,
307 $ tau(l+1), t(l+1, l+1), ldt)
308*
309* Compute T_{1,2}
310* T_{1,2} = V_{2,1}'
311*
312 DO j = 1, l
313 DO i = 1, k-l
314 t(j, l+i) = conjg(v(l+i, j))
315 END DO
316 END DO
317*
318* T_{1,2} = T_{1,2}*V_{2,2}
319*
320 CALL ztrmm('Right', 'Lower', 'No transpose', 'Unit', l,
321 $ k-l, one, v(l+1, l+1), ldv, t(1, l+1), ldt)
322
323*
324* T_{1,2} = V_{3,1}'*V_{3,2} + T_{1,2}
325* Note: We assume K <= N, and GEMM will do nothing if N=K
326*
327 CALL zgemm('Conjugate', 'No transpose', l, k-l, n-k, one,
328 $ v(k+1, 1), ldv, v(k+1, l+1), ldv, one,
329 $ t(1, l+1), ldt)
330*
331* At this point, we have that T_{1,2} = V_1'*V_2
332* All that is left is to pre and post multiply by -T_{1,1} and T_{2,2}
333* respectively.
334*
335* T_{1,2} = -T_{1,1}*T_{1,2}
336*
337 CALL ztrmm('Left', 'Upper', 'No transpose', 'Non-unit', l,
338 $ k-l, neg_one, t, ldt, t(1, l+1), ldt)
339*
340* T_{1,2} = T_{1,2}*T_{2,2}
341*
342 CALL ztrmm('Right', 'Upper', 'No transpose', 'Non-unit', l,
343 $ k-l, one, t(l+1, l+1), ldt, t(1, l+1), ldt)
344
345 ELSE IF(lq) THEN
346*
347* Break V apart into 6 components
348*
349* V = |----------------------|
350* |V_{1,1} V_{1,2} V{1,3}|
351* |0 V_{2,2} V{2,3}|
352* |----------------------|
353*
354* V_{1,1}\in\C^{l,l} unit upper triangular
355* V_{1,2}\in\C^{l,k-l} rectangular
356* V_{1,3}\in\C^{l,n-k} rectangular
357*
358* V_{2,2}\in\C^{k-l,k-l} unit upper triangular
359* V_{2,3}\in\C^{k-l,n-k} rectangular
360*
361* Where l = floor(k/2)
362*
363* We will construct the T matrix
364* T = |---------------|
365* |T_{1,1} T_{1,2}|
366* |0 T_{2,2}|
367* |---------------|
368*
369* T is the triangular factor obtained from block reflectors.
370* To motivate the structure, assume we have already computed T_{1,1}
371* and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
372*
373* T_{1,1}\in\C^{l, l} upper triangular
374* T_{2,2}\in\C^{k-l, k-l} upper triangular
375* T_{1,2}\in\C^{l, k-l} rectangular
376*
377* Then, consider the product:
378*
379* (I - V_1'*T_{1,1}*V_1)*(I - V_2'*T_{2,2}*V_2)
380* = I - V_1'*T_{1,1}*V_1 - V_2'*T_{2,2}*V_2 + V_1'*T_{1,1}*V_1*V_2'*T_{2,2}*V_2
381*
382* Define T_{1,2} = -T_{1,1}*V_1*V_2'*T_{2,2}
383*
384* Then, we can define the matrix V as
385* V = |---|
386* |V_1|
387* |V_2|
388* |---|
389*
390* So, our product is equivalent to the matrix product
391* I - V'*T*V
392* This means, we can compute T_{1,1} and T_{2,2}, then use this information
393* to compute T_{1,2}
394*
395* Compute T_{1,1} recursively
396*
397 CALL zlarft(direct, storev, n, l, v, ldv, tau, t, ldt)
398*
399* Compute T_{2,2} recursively
400*
401 CALL zlarft(direct, storev, n-l, k-l, v(l+1, l+1), ldv,
402 $ tau(l+1), t(l+1, l+1), ldt)
403
404*
405* Compute T_{1,2}
406* T_{1,2} = V_{1,2}
407*
408 CALL zlacpy('All', l, k-l, v(1, l+1), ldv, t(1, l+1), ldt)
409*
410* T_{1,2} = T_{1,2}*V_{2,2}'
411*
412 CALL ztrmm('Right', 'Upper', 'Conjugate', 'Unit', l, k-l,
413 $ one, v(l+1, l+1), ldv, t(1, l+1), ldt)
414
415*
416* T_{1,2} = V_{1,3}*V_{2,3}' + T_{1,2}
417* Note: We assume K <= N, and GEMM will do nothing if N=K
418*
419 CALL zgemm('No transpose', 'Conjugate', l, k-l, n-k, one,
420 $ v(1, k+1), ldv, v(l+1, k+1), ldv, one,
421 $ t(1, l+1), ldt)
422*
423* At this point, we have that T_{1,2} = V_1*V_2'
424* All that is left is to pre and post multiply by -T_{1,1} and T_{2,2}
425* respectively.
426*
427* T_{1,2} = -T_{1,1}*T_{1,2}
428*
429 CALL ztrmm('Left', 'Upper', 'No transpose', 'Non-unit', l,
430 $ k-l, neg_one, t, ldt, t(1, l+1), ldt)
431
432*
433* T_{1,2} = T_{1,2}*T_{2,2}
434*
435 CALL ztrmm('Right', 'Upper', 'No transpose', 'Non-unit', l,
436 $ k-l, one, t(l+1, l+1), ldt, t(1, l+1), ldt)
437 ELSE IF(ql) THEN
438*
439* Break V apart into 6 components
440*
441* V = |---------------|
442* |V_{1,1} V_{1,2}|
443* |V_{2,1} V_{2,2}|
444* |0 V_{3,2}|
445* |---------------|
446*
447* V_{1,1}\in\C^{n-k,k-l} rectangular
448* V_{2,1}\in\C^{k-l,k-l} unit upper triangular
449*
450* V_{1,2}\in\C^{n-k,l} rectangular
451* V_{2,2}\in\C^{k-l,l} rectangular
452* V_{3,2}\in\C^{l,l} unit upper triangular
453*
454* We will construct the T matrix
455* T = |---------------|
456* |T_{1,1} 0 |
457* |T_{2,1} T_{2,2}|
458* |---------------|
459*
460* T is the triangular factor obtained from block reflectors.
461* To motivate the structure, assume we have already computed T_{1,1}
462* and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
463*
464* T_{1,1}\in\C^{k-l, k-l} non-unit lower triangular
465* T_{2,2}\in\C^{l, l} non-unit lower triangular
466* T_{2,1}\in\C^{k-l, l} rectangular
467*
468* Where l = floor(k/2)
469*
470* Then, consider the product:
471*
472* (I - V_2*T_{2,2}*V_2')*(I - V_1*T_{1,1}*V_1')
473* = I - V_2*T_{2,2}*V_2' - V_1*T_{1,1}*V_1' + V_2*T_{2,2}*V_2'*V_1*T_{1,1}*V_1'
474*
475* Define T_{2,1} = -T_{2,2}*V_2'*V_1*T_{1,1}
476*
477* Then, we can define the matrix V as
478* V = |-------|
479* |V_1 V_2|
480* |-------|
481*
482* So, our product is equivalent to the matrix product
483* I - V*T*V'
484* This means, we can compute T_{1,1} and T_{2,2}, then use this information
485* to compute T_{2,1}
486*
487* Compute T_{1,1} recursively
488*
489 CALL zlarft(direct, storev, n-l, k-l, v, ldv, tau, t, ldt)
490*
491* Compute T_{2,2} recursively
492*
493 CALL zlarft(direct, storev, n, l, v(1, k-l+1), ldv,
494 $ tau(k-l+1), t(k-l+1, k-l+1), ldt)
495*
496* Compute T_{2,1}
497* T_{2,1} = V_{2,2}'
498*
499 DO j = 1, k-l
500 DO i = 1, l
501 t(k-l+i, j) = conjg(v(n-k+j, k-l+i))
502 END DO
503 END DO
504*
505* T_{2,1} = T_{2,1}*V_{2,1}
506*
507 CALL ztrmm('Right', 'Upper', 'No transpose', 'Unit', l,
508 $ k-l, one, v(n-k+1, 1), ldv, t(k-l+1, 1), ldt)
509
510*
511* T_{2,1} = V_{2,2}'*V_{2,1} + T_{2,1}
512* Note: We assume K <= N, and GEMM will do nothing if N=K
513*
514 CALL zgemm('Conjugate', 'No transpose', l, k-l, n-k, one,
515 $ v(1, k-l+1), ldv, v, ldv, one, t(k-l+1, 1),
516 $ ldt)
517*
518* At this point, we have that T_{2,1} = V_2'*V_1
519* All that is left is to pre and post multiply by -T_{2,2} and T_{1,1}
520* respectively.
521*
522* T_{2,1} = -T_{2,2}*T_{2,1}
523*
524 CALL ztrmm('Left', 'Lower', 'No transpose', 'Non-unit', l,
525 $ k-l, neg_one, t(k-l+1, k-l+1), ldt,
526 $ t(k-l+1, 1), ldt)
527*
528* T_{2,1} = T_{2,1}*T_{1,1}
529*
530 CALL ztrmm('Right', 'Lower', 'No transpose', 'Non-unit', l,
531 $ k-l, one, t, ldt, t(k-l+1, 1), ldt)
532 ELSE
533*
534* Else means RQ case
535*
536* Break V apart into 6 components
537*
538* V = |-----------------------|
539* |V_{1,1} V_{1,2} 0 |
540* |V_{2,1} V_{2,2} V_{2,3}|
541* |-----------------------|
542*
543* V_{1,1}\in\C^{k-l,n-k} rectangular
544* V_{1,2}\in\C^{k-l,k-l} unit lower triangular
545*
546* V_{2,1}\in\C^{l,n-k} rectangular
547* V_{2,2}\in\C^{l,k-l} rectangular
548* V_{2,3}\in\C^{l,l} unit lower triangular
549*
550* We will construct the T matrix
551* T = |---------------|
552* |T_{1,1} 0 |
553* |T_{2,1} T_{2,2}|
554* |---------------|
555*
556* T is the triangular factor obtained from block reflectors.
557* To motivate the structure, assume we have already computed T_{1,1}
558* and T_{2,2}. Then collect the associated reflectors in V_1 and V_2
559*
560* T_{1,1}\in\C^{k-l, k-l} non-unit lower triangular
561* T_{2,2}\in\C^{l, l} non-unit lower triangular
562* T_{2,1}\in\C^{k-l, l} rectangular
563*
564* Where l = floor(k/2)
565*
566* Then, consider the product:
567*
568* (I - V_2'*T_{2,2}*V_2)*(I - V_1'*T_{1,1}*V_1)
569* = I - V_2'*T_{2,2}*V_2 - V_1'*T_{1,1}*V_1 + V_2'*T_{2,2}*V_2*V_1'*T_{1,1}*V_1
570*
571* Define T_{2,1} = -T_{2,2}*V_2*V_1'*T_{1,1}
572*
573* Then, we can define the matrix V as
574* V = |---|
575* |V_1|
576* |V_2|
577* |---|
578*
579* So, our product is equivalent to the matrix product
580* I - V'*T*V
581* This means, we can compute T_{1,1} and T_{2,2}, then use this information
582* to compute T_{2,1}
583*
584* Compute T_{1,1} recursively
585*
586 CALL zlarft(direct, storev, n-l, k-l, v, ldv, tau, t, ldt)
587*
588* Compute T_{2,2} recursively
589*
590 CALL zlarft(direct, storev, n, l, v(k-l+1, 1), ldv,
591 $ tau(k-l+1), t(k-l+1, k-l+1), ldt)
592*
593* Compute T_{2,1}
594* T_{2,1} = V_{2,2}
595*
596 CALL zlacpy('All', l, k-l, v(k-l+1, n-k+1), ldv,
597 $ t(k-l+1, 1), ldt)
598
599*
600* T_{2,1} = T_{2,1}*V_{1,2}'
601*
602 CALL ztrmm('Right', 'Lower', 'Conjugate', 'Unit', l, k-l,
603 $ one, v(1, n-k+1), ldv, t(k-l+1, 1), ldt)
604
605*
606* T_{2,1} = V_{2,1}*V_{1,1}' + T_{2,1}
607* Note: We assume K <= N, and GEMM will do nothing if N=K
608*
609 CALL zgemm('No transpose', 'Conjugate', l, k-l, n-k, one,
610 $ v(k-l+1, 1), ldv, v, ldv, one, t(k-l+1, 1),
611 $ ldt)
612
613*
614* At this point, we have that T_{2,1} = V_2*V_1'
615* All that is left is to pre and post multiply by -T_{2,2} and T_{1,1}
616* respectively.
617*
618* T_{2,1} = -T_{2,2}*T_{2,1}
619*
620 CALL ztrmm('Left', 'Lower', 'No tranpose', 'Non-unit', l,
621 $ k-l, neg_one, t(k-l+1, k-l+1), ldt,
622 $ t(k-l+1, 1), ldt)
623
624*
625* T_{2,1} = T_{2,1}*T_{1,1}
626*
627 CALL ztrmm('Right', 'Lower', 'No tranpose', 'Non-unit', l,
628 $ k-l, one, t, ldt, t(k-l+1, 1), ldt)
629 END IF
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
Definition zgemm.f:188
subroutine zlacpy(uplo, m, n, a, lda, b, ldb)
ZLACPY copies all or part of one two-dimensional array to another.
Definition zlacpy.f:101
recursive subroutine zlarft(direct, storev, n, k, v, ldv, tau, t, ldt)
ZLARFT forms the triangular factor T of a block reflector H = I - vtvH
Definition zlarft.f:162
logical function lsame(ca, cb)
LSAME
Definition lsame.f:48
subroutine ztrmm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
ZTRMM
Definition ztrmm.f:177
Here is the call graph for this function:
Here is the caller graph for this function: