1 *> \brief \b DLARFB applies a block reflector or its transpose to a general rectangular matrix.
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download DLARFB + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarfb.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarfb.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarfb.f">
21 * SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
22 * T, LDT, C, LDC, WORK, LDWORK )
24 * .. Scalar Arguments ..
25 * CHARACTER DIRECT, SIDE, STOREV, TRANS
26 * INTEGER K, LDC, LDT, LDV, LDWORK, M, N
28 * .. Array Arguments ..
29 * DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
39 *> DLARFB applies a real block reflector H or its transpose H**T to a
40 *> real m by n matrix C, from either the left or the right.
48 *> SIDE is CHARACTER*1
49 *> = 'L': apply H or H**T from the Left
50 *> = 'R': apply H or H**T from the Right
55 *> TRANS is CHARACTER*1
56 *> = 'N': apply H (No transpose)
57 *> = 'T': apply H**T (Transpose)
62 *> DIRECT is CHARACTER*1
63 *> Indicates how H is formed from a product of elementary
65 *> = 'F': H = H(1) H(2) . . . H(k) (Forward)
66 *> = 'B': H = H(k) . . . H(2) H(1) (Backward)
71 *> STOREV is CHARACTER*1
72 *> Indicates how the vectors which define the elementary
73 *> reflectors are stored:
81 *> The number of rows of the matrix C.
87 *> The number of columns of the matrix C.
93 *> The order of the matrix T (= the number of elementary
94 *> reflectors whose product defines the block reflector).
99 *> V is DOUBLE PRECISION array, dimension
100 *> (LDV,K) if STOREV = 'C'
101 *> (LDV,M) if STOREV = 'R' and SIDE = 'L'
102 *> (LDV,N) if STOREV = 'R' and SIDE = 'R'
103 *> The matrix V. See Further Details.
109 *> The leading dimension of the array V.
110 *> If STOREV = 'C' and SIDE = 'L', LDV >= max(1,M);
111 *> if STOREV = 'C' and SIDE = 'R', LDV >= max(1,N);
112 *> if STOREV = 'R', LDV >= K.
117 *> T is DOUBLE PRECISION array, dimension (LDT,K)
118 *> The triangular k by k matrix T in the representation of the
125 *> The leading dimension of the array T. LDT >= K.
130 *> C is DOUBLE PRECISION array, dimension (LDC,N)
131 *> On entry, the m by n matrix C.
132 *> On exit, C is overwritten by H*C or H**T*C or C*H or C*H**T.
138 *> The leading dimension of the array C. LDC >= max(1,M).
143 *> WORK is DOUBLE PRECISION array, dimension (LDWORK,K)
149 *> The leading dimension of the array WORK.
150 *> If SIDE = 'L', LDWORK >= max(1,N);
151 *> if SIDE = 'R', LDWORK >= max(1,M).
157 *> \author Univ. of Tennessee
158 *> \author Univ. of California Berkeley
159 *> \author Univ. of Colorado Denver
164 *> \ingroup doubleOTHERauxiliary
166 *> \par Further Details:
167 * =====================
171 *> The shape of the matrix V and the storage of the vectors which define
172 *> the H(i) is best illustrated by the following example with n = 5 and
173 *> k = 3. The elements equal to 1 are not stored; the corresponding
174 *> array elements are modified but restored on exit. The rest of the
175 *> array is not used.
177 *> DIRECT = 'F' and STOREV = 'C': DIRECT = 'F' and STOREV = 'R':
179 *> V = ( 1 ) V = ( 1 v1 v1 v1 v1 )
180 *> ( v1 1 ) ( 1 v2 v2 v2 )
181 *> ( v1 v2 1 ) ( 1 v3 v3 )
185 *> DIRECT = 'B' and STOREV = 'C': DIRECT = 'B' and STOREV = 'R':
187 *> V = ( v1 v2 v3 ) V = ( v1 v1 1 )
188 *> ( v1 v2 v3 ) ( v2 v2 v2 1 )
189 *> ( 1 v2 v3 ) ( v3 v3 v3 v3 1 )
194 * =====================================================================
195 SUBROUTINE DLARFB( SIDE, TRANS, DIRECT, STOREV, M, N, K, V, LDV,
196 $ T, LDT, C, LDC, WORK, LDWORK )
198 * -- LAPACK auxiliary routine (version 3.5.0) --
199 * -- LAPACK is a software package provided by Univ. of Tennessee, --
200 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
203 * .. Scalar Arguments ..
204 CHARACTER DIRECT, SIDE, STOREV, TRANS
205 INTEGER K, LDC, LDT, LDV, LDWORK, M, N
207 * .. Array Arguments ..
208 DOUBLE PRECISION C( LDC, * ), T( LDT, * ), V( LDV, * ),
212 * =====================================================================
216 PARAMETER ( ONE = 1.0D+0 )
218 * .. Local Scalars ..
222 * .. External Functions ..
226 * .. External Subroutines ..
227 EXTERNAL DCOPY, DGEMM, DTRMM
229 * .. Executable Statements ..
231 * Quick return if possible
233 IF( M.LE.0 .OR. N.LE.0 )
236 IF( LSAME( TRANS, 'N' ) ) THEN
242 IF( LSAME( STOREV, 'C' ) ) THEN
244 IF( LSAME( DIRECT, 'F' ) ) THEN
246 * Let V = ( V1 ) (first K rows)
248 * where V1 is unit lower triangular.
250 IF( LSAME( SIDE, 'L' ) ) THEN
252 * Form H * C or H**T * C where C = ( C1 )
255 * W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
260 CALL DCOPY( N, C( J, 1 ), LDC, WORK( 1, J ), 1 )
265 CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', N,
266 $ K, ONE, V, LDV, WORK, LDWORK )
269 * W := W + C2**T * V2
271 CALL DGEMM( 'Transpose', 'No transpose', N, K, M-K,
272 $ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,
273 $ ONE, WORK, LDWORK )
276 * W := W * T**T or W * T
278 CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit', N, K,
279 $ ONE, T, LDT, WORK, LDWORK )
285 * C2 := C2 - V2 * W**T
287 CALL DGEMM( 'No transpose', 'Transpose', M-K, N, K,
288 $ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,
294 CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', N, K,
295 $ ONE, V, LDV, WORK, LDWORK )
301 C( J, I ) = C( J, I ) - WORK( I, J )
305 ELSE IF( LSAME( SIDE, 'R' ) ) THEN
307 * Form C * H or C * H**T where C = ( C1 C2 )
309 * W := C * V = (C1*V1 + C2*V2) (stored in WORK)
314 CALL DCOPY( M, C( 1, J ), 1, WORK( 1, J ), 1 )
319 CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', M,
320 $ K, ONE, V, LDV, WORK, LDWORK )
325 CALL DGEMM( 'No transpose', 'No transpose', M, K, N-K,
326 $ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
327 $ ONE, WORK, LDWORK )
330 * W := W * T or W * T**T
332 CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit', M, K,
333 $ ONE, T, LDT, WORK, LDWORK )
339 * C2 := C2 - W * V2**T
341 CALL DGEMM( 'No transpose', 'Transpose', M, N-K, K,
342 $ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,
348 CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', M, K,
349 $ ONE, V, LDV, WORK, LDWORK )
355 C( I, J ) = C( I, J ) - WORK( I, J )
363 * ( V2 ) (last K rows)
364 * where V2 is unit upper triangular.
366 IF( LSAME( SIDE, 'L' ) ) THEN
368 * Form H * C or H**T * C where C = ( C1 )
371 * W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
376 CALL DCOPY( N, C( M-K+J, 1 ), LDC, WORK( 1, J ), 1 )
381 CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', N,
382 $ K, ONE, V( M-K+1, 1 ), LDV, WORK, LDWORK )
385 * W := W + C1**T * V1
387 CALL DGEMM( 'Transpose', 'No transpose', N, K, M-K,
388 $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
391 * W := W * T**T or W * T
393 CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit', N, K,
394 $ ONE, T, LDT, WORK, LDWORK )
400 * C1 := C1 - V1 * W**T
402 CALL DGEMM( 'No transpose', 'Transpose', M-K, N, K,
403 $ -ONE, V, LDV, WORK, LDWORK, ONE, C, LDC )
408 CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', N, K,
409 $ ONE, V( M-K+1, 1 ), LDV, WORK, LDWORK )
415 C( M-K+J, I ) = C( M-K+J, I ) - WORK( I, J )
419 ELSE IF( LSAME( SIDE, 'R' ) ) THEN
421 * Form C * H or C * H**T where C = ( C1 C2 )
423 * W := C * V = (C1*V1 + C2*V2) (stored in WORK)
428 CALL DCOPY( M, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
433 CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', M,
434 $ K, ONE, V( N-K+1, 1 ), LDV, WORK, LDWORK )
439 CALL DGEMM( 'No transpose', 'No transpose', M, K, N-K,
440 $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
443 * W := W * T or W * T**T
445 CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit', M, K,
446 $ ONE, T, LDT, WORK, LDWORK )
452 * C1 := C1 - W * V1**T
454 CALL DGEMM( 'No transpose', 'Transpose', M, N-K, K,
455 $ -ONE, WORK, LDWORK, V, LDV, ONE, C, LDC )
460 CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', M, K,
461 $ ONE, V( N-K+1, 1 ), LDV, WORK, LDWORK )
467 C( I, N-K+J ) = C( I, N-K+J ) - WORK( I, J )
473 ELSE IF( LSAME( STOREV, 'R' ) ) THEN
475 IF( LSAME( DIRECT, 'F' ) ) THEN
477 * Let V = ( V1 V2 ) (V1: first K columns)
478 * where V1 is unit upper triangular.
480 IF( LSAME( SIDE, 'L' ) ) THEN
482 * Form H * C or H**T * C where C = ( C1 )
485 * W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
490 CALL DCOPY( N, C( J, 1 ), LDC, WORK( 1, J ), 1 )
495 CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', N, K,
496 $ ONE, V, LDV, WORK, LDWORK )
499 * W := W + C2**T * V2**T
501 CALL DGEMM( 'Transpose', 'Transpose', N, K, M-K, ONE,
502 $ C( K+1, 1 ), LDC, V( 1, K+1 ), LDV, ONE,
506 * W := W * T**T or W * T
508 CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit', N, K,
509 $ ONE, T, LDT, WORK, LDWORK )
511 * C := C - V**T * W**T
515 * C2 := C2 - V2**T * W**T
517 CALL DGEMM( 'Transpose', 'Transpose', M-K, N, K, -ONE,
518 $ V( 1, K+1 ), LDV, WORK, LDWORK, ONE,
524 CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', N,
525 $ K, ONE, V, LDV, WORK, LDWORK )
531 C( J, I ) = C( J, I ) - WORK( I, J )
535 ELSE IF( LSAME( SIDE, 'R' ) ) THEN
537 * Form C * H or C * H**T where C = ( C1 C2 )
539 * W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
544 CALL DCOPY( M, C( 1, J ), 1, WORK( 1, J ), 1 )
549 CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit', M, K,
550 $ ONE, V, LDV, WORK, LDWORK )
553 * W := W + C2 * V2**T
555 CALL DGEMM( 'No transpose', 'Transpose', M, K, N-K,
556 $ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,
557 $ ONE, WORK, LDWORK )
560 * W := W * T or W * T**T
562 CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit', M, K,
563 $ ONE, T, LDT, WORK, LDWORK )
571 CALL DGEMM( 'No transpose', 'No transpose', M, N-K, K,
572 $ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV, ONE,
578 CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit', M,
579 $ K, ONE, V, LDV, WORK, LDWORK )
585 C( I, J ) = C( I, J ) - WORK( I, J )
593 * Let V = ( V1 V2 ) (V2: last K columns)
594 * where V2 is unit lower triangular.
596 IF( LSAME( SIDE, 'L' ) ) THEN
598 * Form H * C or H**T * C where C = ( C1 )
601 * W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
606 CALL DCOPY( N, C( M-K+J, 1 ), LDC, WORK( 1, J ), 1 )
611 CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', N, K,
612 $ ONE, V( 1, M-K+1 ), LDV, WORK, LDWORK )
615 * W := W + C1**T * V1**T
617 CALL DGEMM( 'Transpose', 'Transpose', N, K, M-K, ONE,
618 $ C, LDC, V, LDV, ONE, WORK, LDWORK )
621 * W := W * T**T or W * T
623 CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit', N, K,
624 $ ONE, T, LDT, WORK, LDWORK )
626 * C := C - V**T * W**T
630 * C1 := C1 - V1**T * W**T
632 CALL DGEMM( 'Transpose', 'Transpose', M-K, N, K, -ONE,
633 $ V, LDV, WORK, LDWORK, ONE, C, LDC )
638 CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', N,
639 $ K, ONE, V( 1, M-K+1 ), LDV, WORK, LDWORK )
645 C( M-K+J, I ) = C( M-K+J, I ) - WORK( I, J )
649 ELSE IF( LSAME( SIDE, 'R' ) ) THEN
651 * Form C * H or C * H' where C = ( C1 C2 )
653 * W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
658 CALL DCOPY( M, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
663 CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit', M, K,
664 $ ONE, V( 1, N-K+1 ), LDV, WORK, LDWORK )
667 * W := W + C1 * V1**T
669 CALL DGEMM( 'No transpose', 'Transpose', M, K, N-K,
670 $ ONE, C, LDC, V, LDV, ONE, WORK, LDWORK )
673 * W := W * T or W * T**T
675 CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit', M, K,
676 $ ONE, T, LDT, WORK, LDWORK )
684 CALL DGEMM( 'No transpose', 'No transpose', M, N-K, K,
685 $ -ONE, WORK, LDWORK, V, LDV, ONE, C, LDC )
690 CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit', M,
691 $ K, ONE, V( 1, N-K+1 ), LDV, WORK, LDWORK )
697 C( I, N-K+J ) = C( I, N-K+J ) - WORK( I, J )