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
162
*> \date September 2012
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.4.2) --
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 ..
220
INTEGER I, J, LASTV, LASTC, lastv2
222
* .. External Functions ..
224
INTEGER ILADLR, ILADLC
225
EXTERNAL LSAME, ILADLR, ILADLC
227
* .. External Subroutines ..
228
EXTERNAL DCOPY, DGEMM, DTRMM
230
* .. Executable Statements ..
232
* Quick return if possible
234
IF( M.LE.0 .OR. N.LE.0 )
237
IF( LSAME( TRANS, 'N' ) ) THEN
243
IF( LSAME( STOREV, 'C' ) ) THEN
245
IF( LSAME( DIRECT, 'F' ) ) THEN
247
* Let V = ( V1 ) (first K rows)
249
* where V1 is unit lower triangular.
251
IF( LSAME( SIDE, 'L' ) ) THEN
253
* Form H * C or H**T * C where C = ( C1 )
256
LASTV = MAX( K, ILADLR( M, K, V, LDV ) )
257
LASTC = ILADLC( LASTV, N, C, LDC )
259
* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
264
CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
269
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
270
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
271
IF( LASTV.GT.K ) THEN
275
CALL DGEMM( 'Transpose', 'No transpose',
277
$ ONE, C( K+1, 1 ), LDC, V( K+1, 1 ), LDV,
278
$ ONE, WORK, LDWORK )
281
* W := W * T**T or W * T
283
CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
284
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
288
IF( LASTV.GT.K ) THEN
290
* C2 := C2 - V2 * W**T
292
CALL DGEMM( 'No transpose', 'Transpose',
294
$ -ONE, V( K+1, 1 ), LDV, WORK, LDWORK, ONE,
300
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
301
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
307
C( J, I ) = C( J, I ) - WORK( I, J )
311
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
313
* Form C * H or C * H**T where C = ( C1 C2 )
315
LASTV = MAX( K, ILADLR( N, K, V, LDV ) )
316
LASTC = ILADLR( M, LASTV, C, LDC )
318
* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
323
CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
328
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
329
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
330
IF( LASTV.GT.K ) THEN
334
CALL DGEMM( 'No transpose', 'No transpose',
336
$ ONE, C( 1, K+1 ), LDC, V( K+1, 1 ), LDV,
337
$ ONE, WORK, LDWORK )
340
* W := W * T or W * T**T
342
CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
343
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
347
IF( LASTV.GT.K ) THEN
349
* C2 := C2 - W * V2**T
351
CALL DGEMM( 'No transpose', 'Transpose',
353
$ -ONE, WORK, LDWORK, V( K+1, 1 ), LDV, ONE,
359
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
360
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
366
C( I, J ) = C( I, J ) - WORK( I, J )
374
* ( V2 ) (last K rows)
375
* where V2 is unit upper triangular.
377
IF( LSAME( SIDE, 'L' ) ) THEN
379
* Form H * C or H**T * C where C = ( C1 )
382
LASTC = ILADLC( M, N, C, LDC )
384
* W := C**T * V = (C1**T * V1 + C2**T * V2) (stored in WORK)
389
CALL DCOPY( LASTC, C( M-K+J, 1 ), LDC,
395
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
396
$ LASTC, K, ONE, V( M-K+1, 1 ), LDV,
402
CALL DGEMM( 'Transpose', 'No transpose',
403
$ LASTC, K, M-K, ONE, C, LDC, V, LDV,
404
$ ONE, WORK, LDWORK )
407
* W := W * T**T or W * T
409
CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
410
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
416
* C1 := C1 - V1 * W**T
418
CALL DGEMM( 'No transpose', 'Transpose',
419
$ M-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
425
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
426
$ LASTC, K, ONE, V( M-K+1, 1 ), LDV,
433
C( M-K+J, I ) = C( M-K+J, I ) - WORK(I, J)
437
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
439
* Form C * H or C * H**T where C = ( C1 C2 )
441
LASTC = ILADLR( M, N, C, LDC )
443
* W := C * V = (C1*V1 + C2*V2) (stored in WORK)
448
CALL DCOPY( LASTC, C( 1, N-K+J ), 1, WORK( 1, J ), 1 )
453
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
454
$ LASTC, K, ONE, V( N-K+1, 1 ), LDV,
460
CALL DGEMM( 'No transpose', 'No transpose',
461
$ LASTC, K, N-K, ONE, C, LDC, V, LDV,
462
$ ONE, WORK, LDWORK )
465
* W := W * T or W * T**T
467
CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
468
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
474
* C1 := C1 - W * V1**T
476
CALL DGEMM( 'No transpose', 'Transpose',
477
$ LASTC, N-K, K, -ONE, WORK, LDWORK, V, LDV,
483
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
484
$ LASTC, K, ONE, V( N-K+1, 1 ), LDV,
491
C( I, N-K+J ) = C( I, N-K+J ) - WORK(I, J)
497
ELSE IF( LSAME( STOREV, 'R' ) ) THEN
499
IF( LSAME( DIRECT, 'F' ) ) THEN
501
* Let V = ( V1 V2 ) (V1: first K columns)
502
* where V1 is unit upper triangular.
504
IF( LSAME( SIDE, 'L' ) ) THEN
506
* Form H * C or H**T * C where C = ( C1 )
509
LASTV = MAX( K, ILADLC( K, M, V, LDV ) )
510
LASTC = ILADLC( LASTV, N, C, LDC )
512
* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
517
CALL DCOPY( LASTC, C( J, 1 ), LDC, WORK( 1, J ), 1 )
522
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
523
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
524
IF( LASTV.GT.K ) THEN
526
* W := W + C2**T*V2**T
528
CALL DGEMM( 'Transpose', 'Transpose',
530
$ ONE, C( K+1, 1 ), LDC, V( 1, K+1 ), LDV,
531
$ ONE, WORK, LDWORK )
534
* W := W * T**T or W * T
536
CALL DTRMM( 'Right', 'Upper', TRANST, 'Non-unit',
537
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
539
* C := C - V**T * W**T
541
IF( LASTV.GT.K ) THEN
543
* C2 := C2 - V2**T * W**T
545
CALL DGEMM( 'Transpose', 'Transpose',
547
$ -ONE, V( 1, K+1 ), LDV, WORK, LDWORK,
548
$ ONE, C( K+1, 1 ), LDC )
553
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
554
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
560
C( J, I ) = C( J, I ) - WORK( I, J )
564
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
566
* Form C * H or C * H**T where C = ( C1 C2 )
568
LASTV = MAX( K, ILADLC( K, N, V, LDV ) )
569
LASTC = ILADLR( M, LASTV, C, LDC )
571
* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
576
CALL DCOPY( LASTC, C( 1, J ), 1, WORK( 1, J ), 1 )
581
CALL DTRMM( 'Right', 'Upper', 'Transpose', 'Unit',
582
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
583
IF( LASTV.GT.K ) THEN
585
* W := W + C2 * V2**T
587
CALL DGEMM( 'No transpose', 'Transpose',
589
$ ONE, C( 1, K+1 ), LDC, V( 1, K+1 ), LDV,
590
$ ONE, WORK, LDWORK )
593
* W := W * T or W * T**T
595
CALL DTRMM( 'Right', 'Upper', TRANS, 'Non-unit',
596
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
600
IF( LASTV.GT.K ) THEN
604
CALL DGEMM( 'No transpose', 'No transpose',
606
$ -ONE, WORK, LDWORK, V( 1, K+1 ), LDV,
607
$ ONE, C( 1, K+1 ), LDC )
612
CALL DTRMM( 'Right', 'Upper', 'No transpose', 'Unit',
613
$ LASTC, K, ONE, V, LDV, WORK, LDWORK )
619
C( I, J ) = C( I, J ) - WORK( I, J )
627
* Let V = ( V1 V2 ) (V2: last K columns)
628
* where V2 is unit lower triangular.
630
IF( LSAME( SIDE, 'L' ) ) THEN
632
* Form H * C or H**T * C where C = ( C1 )
635
LASTC = ILADLC( M, N, C, LDC )
637
* W := C**T * V**T = (C1**T * V1**T + C2**T * V2**T) (stored in WORK)
642
CALL DCOPY( LASTC, C( M-K+J, 1 ), LDC,
648
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
649
$ LASTC, K, ONE, V( 1, M-K+1 ), LDV,
653
* W := W + C1**T * V1**T
655
CALL DGEMM( 'Transpose', 'Transpose',
656
$ LASTC, K, M-K, ONE, C, LDC, V, LDV,
657
$ ONE, WORK, LDWORK )
660
* W := W * T**T or W * T
662
CALL DTRMM( 'Right', 'Lower', TRANST, 'Non-unit',
663
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
665
* C := C - V**T * W**T
669
* C1 := C1 - V1**T * W**T
671
CALL DGEMM( 'Transpose', 'Transpose',
672
$ M-K, LASTC, K, -ONE, V, LDV, WORK, LDWORK,
678
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
679
$ LASTC, K, ONE, V( 1, M-K+1 ), LDV,
686
C( M-K+J, I ) = C( M-K+J, I ) - WORK(I, J)
690
ELSE IF( LSAME( SIDE, 'R' ) ) THEN
692
* Form C * H or C * H**T where C = ( C1 C2 )
694
LASTC = ILADLR( M, N, C, LDC )
696
* W := C * V**T = (C1*V1**T + C2*V2**T) (stored in WORK)
701
CALL DCOPY( LASTC, C( 1, N-K+J ), 1,
707
CALL DTRMM( 'Right', 'Lower', 'Transpose', 'Unit',
708
$ LASTC, K, ONE, V( 1, N-K+1 ), LDV,
712
* W := W + C1 * V1**T
714
CALL DGEMM( 'No transpose', 'Transpose',
715
$ LASTC, K, N-K, ONE, C, LDC, V, LDV,
716
$ ONE, WORK, LDWORK )
719
* W := W * T or W * T**T
721
CALL DTRMM( 'Right', 'Lower', TRANS, 'Non-unit',
722
$ LASTC, K, ONE, T, LDT, WORK, LDWORK )
730
CALL DGEMM( 'No transpose', 'No transpose',
731
$ LASTC, N-K, K, -ONE, WORK, LDWORK, V, LDV,
737
CALL DTRMM( 'Right', 'Lower', 'No transpose', 'Unit',
738
$ LASTC, K, ONE, V( 1, N-K+1 ), LDV,
745
C( I, N-K+J ) = C( I, N-K+J ) - WORK(I, J)