1
SUBROUTINE MB01RY( SIDE, UPLO, TRANS, M, ALPHA, BETA, R, LDR, H,
2
$ LDH, B, LDB, DWORK, INFO )
4
C RELEASE 4.0, WGS COPYRIGHT 1999.
8
C To compute either the upper or lower triangular part of one of the
11
C R = alpha*R + beta*op( H )*B, (1)
13
C R = alpha*R + beta*B*op( H ), (2)
15
C where alpha and beta are scalars, H, B, R, and R are m-by-m
16
C matrices, H is an upper Hessenberg matrix, and op( H ) is one of
18
C op( H ) = H or op( H ) = H', the transpose of H.
20
C The result is overwritten on R.
27
C Specifies whether the Hessenberg matrix H appears on the
28
C left or right in the matrix product as follows:
30
C = 'L': R = alpha*R + beta*op( H )*B;
32
C = 'R': R = alpha*R + beta*B*op( H ).
35
C Specifies which triangles of the matrices R and R are
36
C computed and given, respectively, as follows:
37
C = 'U': the upper triangular part;
38
C = 'L': the lower triangular part.
41
C Specifies the form of op( H ) to be used in the matrix
42
C multiplication as follows:
44
C = 'T': op( H ) = H';
45
C = 'C': op( H ) = H'.
47
C Input/Output Parameters
50
C The order of the matrices R, R, H and B. M >= 0.
52
C ALPHA (input) DOUBLE PRECISION
53
C The scalar alpha. When alpha is zero then R need not be
56
C BETA (input) DOUBLE PRECISION
57
C The scalar beta. When beta is zero then H and B are not
60
C R (input/output) DOUBLE PRECISION array, dimension (LDR,M)
61
C On entry with UPLO = 'U', the leading M-by-M upper
62
C triangular part of this array must contain the upper
63
C triangular part of the matrix R; the strictly lower
64
C triangular part of the array is not referenced.
65
C On entry with UPLO = 'L', the leading M-by-M lower
66
C triangular part of this array must contain the lower
67
C triangular part of the matrix R; the strictly upper
68
C triangular part of the array is not referenced.
69
C On exit, the leading M-by-M upper triangular part (if
70
C UPLO = 'U'), or lower triangular part (if UPLO = 'L') of
71
C this array contains the corresponding triangular part of
73
C the computed matrix R.
76
C The leading dimension of array R. LDR >= MAX(1,M).
78
C H (input) DOUBLE PRECISION array, dimension (LDH,M)
79
C On entry, the leading M-by-M upper Hessenberg part of
80
C this array must contain the upper Hessenberg part of the
82
C The elements below the subdiagonal are not referenced,
83
C except possibly for those in the first column, which
84
C could be overwritten, but are restored on exit.
87
C The leading dimension of array H. LDH >= MAX(1,M).
89
C B (input) DOUBLE PRECISION array, dimension (LDB,M)
90
C On entry, the leading M-by-M part of this array must
91
C contain the matrix B.
94
C The leading dimension of array B. LDB >= MAX(1,M).
98
C DWORK DOUBLE PRECISION array, dimension (LDWORK)
99
C LDWORK >= M, if beta <> 0 and SIDE = 'L';
100
C LDWORK >= 0, if beta = 0 or SIDE = 'R'.
101
C This array is not referenced when beta = 0 or SIDE = 'R'.
106
C = 0: successful exit;
107
C < 0: if INFO = -i, the i-th argument had an illegal
112
C The matrix expression is efficiently evaluated taking the
113
C Hessenberg/triangular structure into account. BLAS 2 operations
114
C are used. A block algorithm can be constructed; it can use BLAS 3
115
C GEMM operations for most computations, and calls of this BLAS 2
116
C algorithm for computing the triangles.
120
C The main application of this routine is when the result should
121
C be a symmetric matrix, e.g., when B = X*op( H )', for (1), or
122
C B = op( H )'*X, for (2), where B is already available and X = X'.
126
C V. Sima, Katholieke Univ. Leuven, Belgium, Feb. 1999.
134
C Elementary matrix operations, matrix algebra, matrix operations.
136
C ******************************************************************
139
DOUBLE PRECISION ZERO, ONE
140
PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )
141
C .. Scalar Arguments ..
142
CHARACTER SIDE, TRANS, UPLO
143
INTEGER INFO, LDB, LDH, LDR, M
144
DOUBLE PRECISION ALPHA, BETA
145
C .. Array Arguments ..
146
DOUBLE PRECISION B(LDB,*), DWORK(*), H(LDH,*), R(LDR,*)
147
C .. Local Scalars ..
148
LOGICAL LSIDE, LTRANS, LUPLO
150
C .. External Functions ..
152
DOUBLE PRECISION DDOT
154
C .. External Subroutines ..
155
EXTERNAL DCOPY, DGEMV, DLASCL, DLASET, DSCAL, DSWAP,
157
C .. Intrinsic Functions ..
159
C .. Executable Statements ..
161
C Test the input scalar arguments.
164
LSIDE = LSAME( SIDE, 'L' )
165
LUPLO = LSAME( UPLO, 'U' )
166
LTRANS = LSAME( TRANS, 'T' ) .OR. LSAME( TRANS, 'C' )
168
IF( ( .NOT.LSIDE ).AND.( .NOT.LSAME( SIDE, 'R' ) ) )THEN
170
ELSE IF( ( .NOT.LUPLO ).AND.( .NOT.LSAME( UPLO, 'L' ) ) )THEN
172
ELSE IF( ( .NOT.LTRANS ).AND.( .NOT.LSAME( TRANS, 'N' ) ) )THEN
174
ELSE IF( M.LT.0 ) THEN
176
ELSE IF( LDR.LT.MAX( 1, M ) ) THEN
178
ELSE IF( LDH.LT.MAX( 1, M ) ) THEN
180
ELSE IF( LDB.LT.MAX( 1, M ) ) THEN
184
IF ( INFO.NE.0 ) THEN
188
CALL XERBLA( 'MB01RY', -INFO )
192
C Quick return if possible.
197
IF ( BETA.EQ.ZERO ) THEN
198
IF ( ALPHA.EQ.ZERO ) THEN
200
C Special case when both alpha = 0 and beta = 0.
202
CALL DLASET( UPLO, M, M, ZERO, ZERO, R, LDR )
205
C Special case beta = 0.
208
$ CALL DLASCL( UPLO, 0, 0, ONE, ALPHA, M, M, R, LDR, INFO )
213
C General case: beta <> 0.
214
C Compute the required triangle of (1) or (2) using BLAS 2
219
C To avoid repeated references to the subdiagonal elements of H,
220
C these are swapped with the corresponding elements of H in the
221
C first column, and are finally restored.
224
$ CALL DSWAP( M-2, H( 3, 2 ), LDH+1, H( 3, 1 ), 1 )
231
C Multiply the transposed upper triangle of the leading
232
C j-by-j submatrix of H by the leading part of the j-th
235
CALL DCOPY( J, B( 1, J ), 1, DWORK, 1 )
236
CALL DTRMV( 'Upper', TRANS, 'Non-unit', J, H, LDH,
239
C Add the contribution of the subdiagonal of H to
240
C the j-th column of the product.
242
DO 10 I = 1, MIN( J, M - 1 )
243
R( I, J ) = ALPHA*R( I, J ) + BETA*( DWORK( I ) +
244
$ H( I+1, 1 )*B( I+1, J ) )
249
R( M, M ) = ALPHA*R( M, M ) + BETA*DWORK( M )
255
C Multiply the upper triangle of the leading j-by-j
256
C submatrix of H by the leading part of the j-th column
259
CALL DCOPY( J, B( 1, J ), 1, DWORK, 1 )
260
CALL DTRMV( 'Upper', TRANS, 'Non-unit', J, H, LDH,
264
C Multiply the remaining right part of the leading
265
C j-by-M submatrix of H by the trailing part of the
268
CALL DGEMV( TRANS, J, M-J, BETA, H( 1, J+1 ), LDH,
269
$ B( J+1, J ), 1, ALPHA, R( 1, J ), 1 )
271
CALL DSCAL( M, ALPHA, R( 1, M ), 1 )
274
C Add the contribution of the subdiagonal of H to
275
C the j-th column of the product.
277
R( 1, J ) = R( 1, J ) + BETA*DWORK( 1 )
280
R( I, J ) = R( I, J ) + BETA*( DWORK( I ) +
281
$ H( I, 1 )*B( I-1, J ) )
294
C Multiply the transposed upper triangle of the trailing
295
C (M-j+1)-by-(M-j+1) submatrix of H by the trailing part
296
C of the j-th column of B.
298
CALL DCOPY( M-J+1, B( J, J ), 1, DWORK( J ), 1 )
299
CALL DTRMV( 'Upper', TRANS, 'Non-unit', M-J+1,
300
$ H( J, J ), LDH, DWORK( J ), 1 )
303
C Multiply the remaining left part of the trailing
304
C (M-j+1)-by-(j-1) submatrix of H' by the leading
305
C part of the j-th column of B.
307
CALL DGEMV( TRANS, J-1, M-J+1, BETA, H( 1, J ),
308
$ LDH, B( 1, J ), 1, ALPHA, R( J, J ),
311
CALL DSCAL( M, ALPHA, R( 1, 1 ), 1 )
314
C Add the contribution of the subdiagonal of H to
315
C the j-th column of the product.
318
R( I, J ) = R( I, J ) + BETA*( DWORK( I ) +
319
$ H( I+1, 1 )*B( I+1, J ) )
322
R( M, J ) = R( M, J ) + BETA*DWORK( M )
329
C Multiply the upper triangle of the trailing
330
C (M-j+1)-by-(M-j+1) submatrix of H by the trailing
331
C part of the j-th column of B.
333
CALL DCOPY( M-J+1, B( J, J ), 1, DWORK( J ), 1 )
334
CALL DTRMV( 'Upper', TRANS, 'Non-unit', M-J+1,
335
$ H( J, J ), LDH, DWORK( J ), 1 )
337
C Add the contribution of the subdiagonal of H to
338
C the j-th column of the product.
340
DO 70 I = MAX( J, 2 ), M
341
R( I, J ) = ALPHA*R( I, J ) + BETA*( DWORK( I )
342
$ + H( I, 1 )*B( I-1, J ) )
347
R( 1, 1 ) = ALPHA*R( 1, 1 ) + BETA*DWORK( 1 )
353
$ CALL DSWAP( M-2, H( 3, 2 ), LDH+1, H( 3, 1 ), 1 )
357
C Row-wise calculations are used for H, if SIDE = 'R' and
362
R( 1, 1 ) = ALPHA*R( 1, 1 ) +
363
$ BETA*DDOT( M, B, LDB, H, LDH )
366
CALL DGEMV( 'NoTranspose', J, M-J+2, BETA,
367
$ B( 1, J-1 ), LDB, H( J, J-1 ), LDH,
368
$ ALPHA, R( 1, J ), 1 )
374
CALL DGEMV( 'NoTranspose', J, J+1, BETA, B, LDB,
375
$ H( 1, J ), 1, ALPHA, R( 1, J ), 1 )
378
CALL DGEMV( 'NoTranspose', M, M, BETA, B, LDB,
379
$ H( 1, M ), 1, ALPHA, R( 1, M ), 1 )
387
CALL DGEMV( 'NoTranspose', M, M, BETA, B, LDB, H, LDH,
388
$ ALPHA, R( 1, 1 ), 1 )
391
CALL DGEMV( 'NoTranspose', M-J+1, M-J+2, BETA,
392
$ B( J, J-1 ), LDB, H( J, J-1 ), LDH, ALPHA,
399
CALL DGEMV( 'NoTranspose', M-J+1, J+1, BETA,
400
$ B( J, 1 ), LDB, H( 1, J ), 1, ALPHA,
404
R( M, M ) = ALPHA*R( M, M ) +
405
$ BETA*DDOT( M, B( M, 1 ), LDB, H( 1, M ), 1 )
412
C *** Last line of MB01RY ***