iexciting-0.9.224
[exciting.git] / src / LAPACK / dsytrs.f
blob163ed5b9a72310b938793d6720fc3d2283e6f083
1 SUBROUTINE DSYTRS( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
3 * -- LAPACK routine (version 3.1) --
4 * Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
5 * November 2006
7 * .. Scalar Arguments ..
8 CHARACTER UPLO
9 INTEGER INFO, LDA, LDB, N, NRHS
10 * ..
11 * .. Array Arguments ..
12 INTEGER IPIV( * )
13 DOUBLE PRECISION A( LDA, * ), B( LDB, * )
14 * ..
16 * Purpose
17 * =======
19 * DSYTRS solves a system of linear equations A*X = B with a real
20 * symmetric matrix A using the factorization A = U*D*U**T or
21 * A = L*D*L**T computed by DSYTRF.
23 * Arguments
24 * =========
26 * UPLO (input) CHARACTER*1
27 * Specifies whether the details of the factorization are stored
28 * as an upper or lower triangular matrix.
29 * = 'U': Upper triangular, form is A = U*D*U**T;
30 * = 'L': Lower triangular, form is A = L*D*L**T.
32 * N (input) INTEGER
33 * The order of the matrix A. N >= 0.
35 * NRHS (input) INTEGER
36 * The number of right hand sides, i.e., the number of columns
37 * of the matrix B. NRHS >= 0.
39 * A (input) DOUBLE PRECISION array, dimension (LDA,N)
40 * The block diagonal matrix D and the multipliers used to
41 * obtain the factor U or L as computed by DSYTRF.
43 * LDA (input) INTEGER
44 * The leading dimension of the array A. LDA >= max(1,N).
46 * IPIV (input) INTEGER array, dimension (N)
47 * Details of the interchanges and the block structure of D
48 * as determined by DSYTRF.
50 * B (input/output) DOUBLE PRECISION array, dimension (LDB,NRHS)
51 * On entry, the right hand side matrix B.
52 * On exit, the solution matrix X.
54 * LDB (input) INTEGER
55 * The leading dimension of the array B. LDB >= max(1,N).
57 * INFO (output) INTEGER
58 * = 0: successful exit
59 * < 0: if INFO = -i, the i-th argument had an illegal value
61 * =====================================================================
63 * .. Parameters ..
64 DOUBLE PRECISION ONE
65 PARAMETER ( ONE = 1.0D+0 )
66 * ..
67 * .. Local Scalars ..
68 LOGICAL UPPER
69 INTEGER J, K, KP
70 DOUBLE PRECISION AK, AKM1, AKM1K, BK, BKM1, DENOM
71 * ..
72 * .. External Functions ..
73 LOGICAL LSAME
74 EXTERNAL LSAME
75 * ..
76 * .. External Subroutines ..
77 EXTERNAL DGEMV, DGER, DSCAL, DSWAP, XERBLA
78 * ..
79 * .. Intrinsic Functions ..
80 INTRINSIC MAX
81 * ..
82 * .. Executable Statements ..
84 INFO = 0
85 UPPER = LSAME( UPLO, 'U' )
86 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
87 INFO = -1
88 ELSE IF( N.LT.0 ) THEN
89 INFO = -2
90 ELSE IF( NRHS.LT.0 ) THEN
91 INFO = -3
92 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
93 INFO = -5
94 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
95 INFO = -8
96 END IF
97 IF( INFO.NE.0 ) THEN
98 CALL XERBLA( 'DSYTRS', -INFO )
99 RETURN
100 END IF
102 * Quick return if possible
104 IF( N.EQ.0 .OR. NRHS.EQ.0 )
105 $ RETURN
107 IF( UPPER ) THEN
109 * Solve A*X = B, where A = U*D*U'.
111 * First solve U*D*X = B, overwriting B with X.
113 * K is the main loop index, decreasing from N to 1 in steps of
114 * 1 or 2, depending on the size of the diagonal blocks.
116 K = N
117 10 CONTINUE
119 * If K < 1, exit from loop.
121 IF( K.LT.1 )
122 $ GO TO 30
124 IF( IPIV( K ).GT.0 ) THEN
126 * 1 x 1 diagonal block
128 * Interchange rows K and IPIV(K).
130 KP = IPIV( K )
131 IF( KP.NE.K )
132 $ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
134 * Multiply by inv(U(K)), where U(K) is the transformation
135 * stored in column K of A.
137 CALL DGER( K-1, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,
138 $ B( 1, 1 ), LDB )
140 * Multiply by the inverse of the diagonal block.
142 CALL DSCAL( NRHS, ONE / A( K, K ), B( K, 1 ), LDB )
143 K = K - 1
144 ELSE
146 * 2 x 2 diagonal block
148 * Interchange rows K-1 and -IPIV(K).
150 KP = -IPIV( K )
151 IF( KP.NE.K-1 )
152 $ CALL DSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )
154 * Multiply by inv(U(K)), where U(K) is the transformation
155 * stored in columns K-1 and K of A.
157 CALL DGER( K-2, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,
158 $ B( 1, 1 ), LDB )
159 CALL DGER( K-2, NRHS, -ONE, A( 1, K-1 ), 1, B( K-1, 1 ),
160 $ LDB, B( 1, 1 ), LDB )
162 * Multiply by the inverse of the diagonal block.
164 AKM1K = A( K-1, K )
165 AKM1 = A( K-1, K-1 ) / AKM1K
166 AK = A( K, K ) / AKM1K
167 DENOM = AKM1*AK - ONE
168 DO 20 J = 1, NRHS
169 BKM1 = B( K-1, J ) / AKM1K
170 BK = B( K, J ) / AKM1K
171 B( K-1, J ) = ( AK*BKM1-BK ) / DENOM
172 B( K, J ) = ( AKM1*BK-BKM1 ) / DENOM
173 20 CONTINUE
174 K = K - 2
175 END IF
177 GO TO 10
178 30 CONTINUE
180 * Next solve U'*X = B, overwriting B with X.
182 * K is the main loop index, increasing from 1 to N in steps of
183 * 1 or 2, depending on the size of the diagonal blocks.
185 K = 1
186 40 CONTINUE
188 * If K > N, exit from loop.
190 IF( K.GT.N )
191 $ GO TO 50
193 IF( IPIV( K ).GT.0 ) THEN
195 * 1 x 1 diagonal block
197 * Multiply by inv(U'(K)), where U(K) is the transformation
198 * stored in column K of A.
200 CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB, A( 1, K ),
201 $ 1, ONE, B( K, 1 ), LDB )
203 * Interchange rows K and IPIV(K).
205 KP = IPIV( K )
206 IF( KP.NE.K )
207 $ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
208 K = K + 1
209 ELSE
211 * 2 x 2 diagonal block
213 * Multiply by inv(U'(K+1)), where U(K+1) is the transformation
214 * stored in columns K and K+1 of A.
216 CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB, A( 1, K ),
217 $ 1, ONE, B( K, 1 ), LDB )
218 CALL DGEMV( 'Transpose', K-1, NRHS, -ONE, B, LDB,
219 $ A( 1, K+1 ), 1, ONE, B( K+1, 1 ), LDB )
221 * Interchange rows K and -IPIV(K).
223 KP = -IPIV( K )
224 IF( KP.NE.K )
225 $ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
226 K = K + 2
227 END IF
229 GO TO 40
230 50 CONTINUE
232 ELSE
234 * Solve A*X = B, where A = L*D*L'.
236 * First solve L*D*X = B, overwriting B with X.
238 * K is the main loop index, increasing from 1 to N in steps of
239 * 1 or 2, depending on the size of the diagonal blocks.
241 K = 1
242 60 CONTINUE
244 * If K > N, exit from loop.
246 IF( K.GT.N )
247 $ GO TO 80
249 IF( IPIV( K ).GT.0 ) THEN
251 * 1 x 1 diagonal block
253 * Interchange rows K and IPIV(K).
255 KP = IPIV( K )
256 IF( KP.NE.K )
257 $ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
259 * Multiply by inv(L(K)), where L(K) is the transformation
260 * stored in column K of A.
262 IF( K.LT.N )
263 $ CALL DGER( N-K, NRHS, -ONE, A( K+1, K ), 1, B( K, 1 ),
264 $ LDB, B( K+1, 1 ), LDB )
266 * Multiply by the inverse of the diagonal block.
268 CALL DSCAL( NRHS, ONE / A( K, K ), B( K, 1 ), LDB )
269 K = K + 1
270 ELSE
272 * 2 x 2 diagonal block
274 * Interchange rows K+1 and -IPIV(K).
276 KP = -IPIV( K )
277 IF( KP.NE.K+1 )
278 $ CALL DSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )
280 * Multiply by inv(L(K)), where L(K) is the transformation
281 * stored in columns K and K+1 of A.
283 IF( K.LT.N-1 ) THEN
284 CALL DGER( N-K-1, NRHS, -ONE, A( K+2, K ), 1, B( K, 1 ),
285 $ LDB, B( K+2, 1 ), LDB )
286 CALL DGER( N-K-1, NRHS, -ONE, A( K+2, K+1 ), 1,
287 $ B( K+1, 1 ), LDB, B( K+2, 1 ), LDB )
288 END IF
290 * Multiply by the inverse of the diagonal block.
292 AKM1K = A( K+1, K )
293 AKM1 = A( K, K ) / AKM1K
294 AK = A( K+1, K+1 ) / AKM1K
295 DENOM = AKM1*AK - ONE
296 DO 70 J = 1, NRHS
297 BKM1 = B( K, J ) / AKM1K
298 BK = B( K+1, J ) / AKM1K
299 B( K, J ) = ( AK*BKM1-BK ) / DENOM
300 B( K+1, J ) = ( AKM1*BK-BKM1 ) / DENOM
301 70 CONTINUE
302 K = K + 2
303 END IF
305 GO TO 60
306 80 CONTINUE
308 * Next solve L'*X = B, overwriting B with X.
310 * K is the main loop index, decreasing from N to 1 in steps of
311 * 1 or 2, depending on the size of the diagonal blocks.
313 K = N
314 90 CONTINUE
316 * If K < 1, exit from loop.
318 IF( K.LT.1 )
319 $ GO TO 100
321 IF( IPIV( K ).GT.0 ) THEN
323 * 1 x 1 diagonal block
325 * Multiply by inv(L'(K)), where L(K) is the transformation
326 * stored in column K of A.
328 IF( K.LT.N )
329 $ CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),
330 $ LDB, A( K+1, K ), 1, ONE, B( K, 1 ), LDB )
332 * Interchange rows K and IPIV(K).
334 KP = IPIV( K )
335 IF( KP.NE.K )
336 $ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
337 K = K - 1
338 ELSE
340 * 2 x 2 diagonal block
342 * Multiply by inv(L'(K-1)), where L(K-1) is the transformation
343 * stored in columns K-1 and K of A.
345 IF( K.LT.N ) THEN
346 CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),
347 $ LDB, A( K+1, K ), 1, ONE, B( K, 1 ), LDB )
348 CALL DGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),
349 $ LDB, A( K+1, K-1 ), 1, ONE, B( K-1, 1 ),
350 $ LDB )
351 END IF
353 * Interchange rows K and -IPIV(K).
355 KP = -IPIV( K )
356 IF( KP.NE.K )
357 $ CALL DSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
358 K = K - 2
359 END IF
361 GO TO 90
362 100 CONTINUE
363 END IF
365 RETURN
367 * End of DSYTRS