1 *> \brief \b SSYTRS_ROOK
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download SSYTRS_ROOK + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/ssytrs_rook.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/ssytrs_rook.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/ssytrs_rook.f">
21 * SUBROUTINE SSYTRS_ROOK( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
23 * .. Scalar Arguments ..
25 * INTEGER INFO, LDA, LDB, N, NRHS
27 * .. Array Arguments ..
29 * REAL A( LDA, * ), B( LDB, * )
38 *> SSYTRS_ROOK solves a system of linear equations A*X = B with
39 *> a real symmetric matrix A using the factorization A = U*D*U**T or
40 *> A = L*D*L**T computed by SSYTRF_ROOK.
48 *> UPLO is CHARACTER*1
49 *> Specifies whether the details of the factorization are stored
50 *> as an upper or lower triangular matrix.
51 *> = 'U': Upper triangular, form is A = U*D*U**T;
52 *> = 'L': Lower triangular, form is A = L*D*L**T.
58 *> The order of the matrix A. N >= 0.
64 *> The number of right hand sides, i.e., the number of columns
65 *> of the matrix B. NRHS >= 0.
70 *> A is REAL array, dimension (LDA,N)
71 *> The block diagonal matrix D and the multipliers used to
72 *> obtain the factor U or L as computed by SSYTRF_ROOK.
78 *> The leading dimension of the array A. LDA >= max(1,N).
83 *> IPIV is INTEGER array, dimension (N)
84 *> Details of the interchanges and the block structure of D
85 *> as determined by SSYTRF_ROOK.
90 *> B is REAL array, dimension (LDB,NRHS)
91 *> On entry, the right hand side matrix B.
92 *> On exit, the solution matrix X.
98 *> The leading dimension of the array B. LDB >= max(1,N).
104 *> = 0: successful exit
105 *> < 0: if INFO = -i, the i-th argument had an illegal value
111 *> \author Univ. of Tennessee
112 *> \author Univ. of California Berkeley
113 *> \author Univ. of Colorado Denver
118 *> \ingroup realSYcomputational
120 *> \par Contributors:
125 *> April 2012, Igor Kozachenko,
126 *> Computer Science Division,
127 *> University of California, Berkeley
129 *> September 2007, Sven Hammarling, Nicholas J. Higham, Craig Lucas,
130 *> School of Mathematics,
131 *> University of Manchester
135 * =====================================================================
136 SUBROUTINE SSYTRS_ROOK( UPLO, N, NRHS, A, LDA, IPIV, B, LDB,
139 * -- LAPACK computational routine (version 3.4.1) --
140 * -- LAPACK is a software package provided by Univ. of Tennessee, --
141 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
144 * .. Scalar Arguments ..
146 INTEGER INFO, LDA, LDB, N, NRHS
148 * .. Array Arguments ..
150 REAL A( LDA, * ), B( LDB, * )
153 * =====================================================================
157 PARAMETER ( ONE = 1.0E+0 )
159 * .. Local Scalars ..
162 REAL AK, AKM1, AKM1K, BK, BKM1, DENOM
164 * .. External Functions ..
168 * .. External Subroutines ..
169 EXTERNAL SGEMV, SGER, SSCAL, SSWAP, XERBLA
171 * .. Intrinsic Functions ..
174 * .. Executable Statements ..
177 UPPER = LSAME( UPLO, 'U' )
178 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
180 ELSE IF( N.LT.0 ) THEN
182 ELSE IF( NRHS.LT.0 ) THEN
184 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
186 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
190 CALL XERBLA( 'SSYTRS_ROOK', -INFO )
194 * Quick return if possible
196 IF( N.EQ.0 .OR. NRHS.EQ.0 )
201 * Solve A*X = B, where A = U*D*U**T.
203 * First solve U*D*X = B, overwriting B with X.
205 * K is the main loop index, decreasing from N to 1 in steps of
206 * 1 or 2, depending on the size of the diagonal blocks.
211 * If K < 1, exit from loop.
216 IF( IPIV( K ).GT.0 ) THEN
218 * 1 x 1 diagonal block
220 * Interchange rows K and IPIV(K).
224 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
226 * Multiply by inv(U(K)), where U(K) is the transformation
227 * stored in column K of A.
229 CALL SGER( K-1, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,
232 * Multiply by the inverse of the diagonal block.
234 CALL SSCAL( NRHS, ONE / A( K, K ), B( K, 1 ), LDB )
238 * 2 x 2 diagonal block
240 * Interchange rows K and -IPIV(K) THEN K-1 and -IPIV(K-1)
244 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
248 $ CALL SSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )
250 * Multiply by inv(U(K)), where U(K) is the transformation
251 * stored in columns K-1 and K of A.
254 CALL SGER( K-2, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ),
255 $ LDB, B( 1, 1 ), LDB )
256 CALL SGER( K-2, NRHS, -ONE, A( 1, K-1 ), 1, B( K-1, 1 ),
257 $ LDB, B( 1, 1 ), LDB )
260 * Multiply by the inverse of the diagonal block.
263 AKM1 = A( K-1, K-1 ) / AKM1K
264 AK = A( K, K ) / AKM1K
265 DENOM = AKM1*AK - ONE
267 BKM1 = B( K-1, J ) / AKM1K
268 BK = B( K, J ) / AKM1K
269 B( K-1, J ) = ( AK*BKM1-BK ) / DENOM
270 B( K, J ) = ( AKM1*BK-BKM1 ) / DENOM
278 * Next solve U**T *X = B, overwriting B with X.
280 * K is the main loop index, increasing from 1 to N in steps of
281 * 1 or 2, depending on the size of the diagonal blocks.
286 * If K > N, exit from loop.
291 IF( IPIV( K ).GT.0 ) THEN
293 * 1 x 1 diagonal block
295 * Multiply by inv(U**T(K)), where U(K) is the transformation
296 * stored in column K of A.
299 $ CALL SGEMV( 'Transpose', K-1, NRHS, -ONE, B,
300 $ LDB, A( 1, K ), 1, ONE, B( K, 1 ), LDB )
302 * Interchange rows K and IPIV(K).
306 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
310 * 2 x 2 diagonal block
312 * Multiply by inv(U**T(K+1)), where U(K+1) is the transformation
313 * stored in columns K and K+1 of A.
316 CALL SGEMV( 'Transpose', K-1, NRHS, -ONE, B,
317 $ LDB, A( 1, K ), 1, ONE, B( K, 1 ), LDB )
318 CALL SGEMV( 'Transpose', K-1, NRHS, -ONE, B,
319 $ LDB, A( 1, K+1 ), 1, ONE, B( K+1, 1 ), LDB )
322 * Interchange rows K and -IPIV(K) THEN K+1 and -IPIV(K+1).
326 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
330 $ CALL SSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )
340 * Solve A*X = B, where A = L*D*L**T.
342 * First solve L*D*X = B, overwriting B with X.
344 * K is the main loop index, increasing from 1 to N in steps of
345 * 1 or 2, depending on the size of the diagonal blocks.
350 * If K > N, exit from loop.
355 IF( IPIV( K ).GT.0 ) THEN
357 * 1 x 1 diagonal block
359 * Interchange rows K and IPIV(K).
363 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
365 * Multiply by inv(L(K)), where L(K) is the transformation
366 * stored in column K of A.
369 $ CALL SGER( N-K, NRHS, -ONE, A( K+1, K ), 1, B( K, 1 ),
370 $ LDB, B( K+1, 1 ), LDB )
372 * Multiply by the inverse of the diagonal block.
374 CALL SSCAL( NRHS, ONE / A( K, K ), B( K, 1 ), LDB )
378 * 2 x 2 diagonal block
380 * Interchange rows K and -IPIV(K) THEN K+1 and -IPIV(K+1)
384 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
388 $ CALL SSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )
390 * Multiply by inv(L(K)), where L(K) is the transformation
391 * stored in columns K and K+1 of A.
394 CALL SGER( N-K-1, NRHS, -ONE, A( K+2, K ), 1, B( K, 1 ),
395 $ LDB, B( K+2, 1 ), LDB )
396 CALL SGER( N-K-1, NRHS, -ONE, A( K+2, K+1 ), 1,
397 $ B( K+1, 1 ), LDB, B( K+2, 1 ), LDB )
400 * Multiply by the inverse of the diagonal block.
403 AKM1 = A( K, K ) / AKM1K
404 AK = A( K+1, K+1 ) / AKM1K
405 DENOM = AKM1*AK - ONE
407 BKM1 = B( K, J ) / AKM1K
408 BK = B( K+1, J ) / AKM1K
409 B( K, J ) = ( AK*BKM1-BK ) / DENOM
410 B( K+1, J ) = ( AKM1*BK-BKM1 ) / DENOM
418 * Next solve L**T *X = B, overwriting B with X.
420 * K is the main loop index, decreasing from N to 1 in steps of
421 * 1 or 2, depending on the size of the diagonal blocks.
426 * If K < 1, exit from loop.
431 IF( IPIV( K ).GT.0 ) THEN
433 * 1 x 1 diagonal block
435 * Multiply by inv(L**T(K)), where L(K) is the transformation
436 * stored in column K of A.
439 $ CALL SGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),
440 $ LDB, A( K+1, K ), 1, ONE, B( K, 1 ), LDB )
442 * Interchange rows K and IPIV(K).
446 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
450 * 2 x 2 diagonal block
452 * Multiply by inv(L**T(K-1)), where L(K-1) is the transformation
453 * stored in columns K-1 and K of A.
456 CALL SGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),
457 $ LDB, A( K+1, K ), 1, ONE, B( K, 1 ), LDB )
458 CALL SGEMV( 'Transpose', N-K, NRHS, -ONE, B( K+1, 1 ),
459 $ LDB, A( K+1, K-1 ), 1, ONE, B( K-1, 1 ),
463 * Interchange rows K and -IPIV(K) THEN K-1 and -IPIV(K-1)
467 $ CALL SSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
471 $ CALL SSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )