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

◆ dlarft()

recursive subroutine dlarft ( character direct,
character storev,
integer n,
integer k,
double precision, dimension( ldv, * ) v,
integer ldv,
double precision, dimension( * ) tau,
double precision, dimension( ldt, * ) t,
integer ldt )

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

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

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