1 SUBROUTINE DTRSM
( SIDE
, UPLO
, TRANSA
, DIAG
, M
, N
, ALPHA
, A
, LDA
,
3 * .. Scalar Arguments
..
4 CHARACTER*1 SIDE
, UPLO
, TRANSA
, DIAG
7 * .. Array Arguments
..
8 DOUBLE PRECISION A
( LDA
, * ), B
( LDB
, * )
14 * DTRSM solves one of the matrix equations
16 * op
( A
)*X
= alpha*B
, or X*op
( A
) = alpha*B
,
18 * where alpha is a scalar
, X and B are m by n matrices
, A is a unit
, or
19 * non
-unit
, upper or lower triangular matrix and op
( A
) is one of
21 * op
( A
) = A or op
( A
) = A
'.
23 * The matrix X is overwritten on B.
29 * On entry, SIDE specifies whether op( A ) appears on the left
30 * or right of X as follows:
32 * SIDE = 'L
' or 'l
' op( A )*X = alpha*B.
34 * SIDE = 'R
' or 'r
' X*op( A ) = alpha*B.
39 * On entry, UPLO specifies whether the matrix A is an upper or
40 * lower triangular matrix as follows:
42 * UPLO = 'U
' or 'u
' A is an upper triangular matrix.
44 * UPLO = 'L
' or 'l
' A is a lower triangular matrix.
48 * TRANSA - CHARACTER*1.
49 * On entry, TRANSA specifies the form of op( A ) to be used in
50 * the matrix multiplication as follows:
52 * TRANSA = 'N
' or 'n
' op( A ) = A.
54 * TRANSA = 'T
' or 't
' op( A ) = A'.
56 * TRANSA
= 'C' or
'c' op
( A
) = A
'.
61 * On entry, DIAG specifies whether or not A is unit triangular
64 * DIAG = 'U
' or 'u
' A is assumed to be unit triangular.
66 * DIAG = 'N
' or 'n
' A is not assumed to be unit
72 * On entry, M specifies the number of rows of B. M must be at
77 * On entry, N specifies the number of columns of B. N must be
81 * ALPHA - DOUBLE PRECISION.
82 * On entry, ALPHA specifies the scalar alpha. When alpha is
83 * zero then A is not referenced and B need not be set before
87 * A - DOUBLE PRECISION array of DIMENSION ( LDA, k ), where k is m
88 * when SIDE = 'L
' or 'l
' and is n when SIDE = 'R
' or 'r
'.
89 * Before entry with UPLO = 'U
' or 'u
', the leading k by k
90 * upper triangular part of the array A must contain the upper
91 * triangular matrix and the strictly lower triangular part of
92 * A is not referenced.
93 * Before entry with UPLO = 'L
' or 'l
', the leading k by k
94 * lower triangular part of the array A must contain the lower
95 * triangular matrix and the strictly upper triangular part of
96 * A is not referenced.
97 * Note that when DIAG = 'U
' or 'u
', the diagonal elements of
98 * A are not referenced either, but are assumed to be unity.
102 * On entry, LDA specifies the first dimension of A as declared
103 * in the calling (sub) program. When SIDE = 'L
' or 'l
' then
104 * LDA must be at least max( 1, m ), when SIDE = 'R
' or 'r
'
105 * then LDA must be at least max( 1, n ).
108 * B - DOUBLE PRECISION array of DIMENSION ( LDB, n ).
109 * Before entry, the leading m by n part of the array B must
110 * contain the right-hand side matrix B, and on exit is
111 * overwritten by the solution matrix X.
114 * On entry, LDB specifies the first dimension of B as declared
115 * in the calling (sub) program. LDB must be at least
120 * Level 3 Blas routine.
123 * -- Written on 8-February-1989.
124 * Jack Dongarra, Argonne National Laboratory.
125 * Iain Duff, AERE Harwell.
126 * Jeremy Du Croz, Numerical Algorithms Group Ltd.
127 * Sven Hammarling, Numerical Algorithms Group Ltd.
130 * .. External Functions ..
133 * .. External Subroutines ..
135 * .. Intrinsic Functions ..
137 * .. Local Scalars ..
138 LOGICAL LSIDE, NOUNIT, UPPER
139 INTEGER I, INFO, J, K, NROWA
140 DOUBLE PRECISION TEMP
142 DOUBLE PRECISION ONE , ZERO
143 PARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )
145 * .. Executable Statements ..
147 * Test the input parameters.
149 LSIDE = LSAME( SIDE , 'L
' )
155 NOUNIT = LSAME( DIAG , 'N
' )
156 UPPER = LSAME( UPLO , 'U
' )
159 IF( ( .NOT.LSIDE ).AND.
160 $ ( .NOT.LSAME( SIDE , 'R
' ) ) )THEN
162 ELSE IF( ( .NOT.UPPER ).AND.
163 $ ( .NOT.LSAME( UPLO , 'L
' ) ) )THEN
165 ELSE IF( ( .NOT.LSAME( TRANSA, 'N
' ) ).AND.
166 $ ( .NOT.LSAME( TRANSA, 'T
' ) ).AND.
167 $ ( .NOT.LSAME( TRANSA, 'C
' ) ) )THEN
169 ELSE IF( ( .NOT.LSAME( DIAG , 'U
' ) ).AND.
170 $ ( .NOT.LSAME( DIAG , 'N
' ) ) )THEN
172 ELSE IF( M .LT.0 )THEN
174 ELSE IF( N .LT.0 )THEN
176 ELSE IF( LDA.LT.MAX( 1, NROWA ) )THEN
178 ELSE IF( LDB.LT.MAX( 1, M ) )THEN
182 CALL XERBLA( 'DTRSM
', INFO )
186 * Quick return if possible.
191 * And when alpha.eq.zero.
193 IF( ALPHA.EQ.ZERO )THEN
202 * Start the operations.
205 IF( LSAME( TRANSA, 'N
' ) )THEN
207 * Form B := alpha*inv( A )*B.
211 IF( ALPHA.NE.ONE )THEN
213 B( I, J ) = ALPHA*B( I, J )
217 IF( B( K, J ).NE.ZERO )THEN
219 $ B( K, J ) = B( K, J )/A( K, K )
221 B( I, J ) = B( I, J ) - B( K, J )*A( I, K )
228 IF( ALPHA.NE.ONE )THEN
230 B( I, J ) = ALPHA*B( I, J )
234 IF( B( K, J ).NE.ZERO )THEN
236 $ B( K, J ) = B( K, J )/A( K, K )
238 B( I, J ) = B( I, J ) - B( K, J )*A( I, K )
246 * Form B := alpha*inv( A' )*B
.
251 TEMP
= ALPHA*B
( I
, J
)
253 TEMP
= TEMP
- A
( K
, I
)*B
( K
, J
)
256 $ TEMP
= TEMP
/A
( I
, I
)
263 TEMP
= ALPHA*B
( I
, J
)
265 TEMP
= TEMP
- A
( K
, I
)*B
( K
, J
)
268 $ TEMP
= TEMP
/A
( I
, I
)
275 IF( LSAME
( TRANSA
, 'N' ) )THEN
277 * Form B
:= alpha*B*inv
( A
).
281 IF( ALPHA
.NE
.ONE
)THEN
283 B
( I
, J
) = ALPHA*B
( I
, J
)
287 IF( A
( K
, J
).NE
.ZERO
)THEN
289 B
( I
, J
) = B
( I
, J
) - A
( K
, J
)*B
( I
, K
)
296 B
( I
, J
) = TEMP*B
( I
, J
)
302 IF( ALPHA
.NE
.ONE
)THEN
304 B
( I
, J
) = ALPHA*B
( I
, J
)
308 IF( A
( K
, J
).NE
.ZERO
)THEN
310 B
( I
, J
) = B
( I
, J
) - A
( K
, J
)*B
( I
, K
)
317 B
( I
, J
) = TEMP*B
( I
, J
)
324 * Form B
:= alpha*B*inv
( A
' ).
331 B( I, K ) = TEMP*B( I, K )
335 IF( A( J, K ).NE.ZERO )THEN
338 B( I, J ) = B( I, J ) - TEMP*B( I, K )
342 IF( ALPHA.NE.ONE )THEN
344 B( I, K ) = ALPHA*B( I, K )
353 B( I, K ) = TEMP*B( I, K )
357 IF( A( J, K ).NE.ZERO )THEN
360 B( I, J ) = B( I, J ) - TEMP*B( I, K )
364 IF( ALPHA.NE.ONE )THEN
366 B( I, K ) = ALPHA*B( I, K )