1 *> \brief \b ZHETRS_ROOK computes the solution to a system of linear equations A * X = B for HE matrices using factorization obtained with one of the bounded diagonal pivoting methods (max 2 interchanges)
3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download ZHETRS_ROOK + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zhetrs_rook.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zhetrs_rook.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhetrs_rook.f">
21 * SUBROUTINE ZHETRS_ROOK( UPLO, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
23 * .. Scalar Arguments ..
25 * INTEGER INFO, LDA, LDB, N, NRHS
27 * .. Array Arguments ..
29 * COMPLEX A( LDA, * ), B( LDB, * )
38 *> ZHETRS_ROOK solves a system of linear equations A*X = B with a complex
39 *> Hermitian matrix A using the factorization A = U*D*U**H or
40 *> A = L*D*L**H computed by ZHETRF_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**H;
52 *> = 'L': Lower triangular, form is A = L*D*L**H.
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 COMPLEX*16 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 ZHETRF_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 ZHETRF_ROOK.
90 *> B is COMPLEX*16 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
116 *> \date November 2013
118 *> \ingroup complex16HEcomputational
120 *> \par Contributors:
125 *> November 2013, 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 ZHETRS_ROOK( UPLO, N, NRHS, A, LDA, IPIV, B, LDB,
139 * -- LAPACK computational routine (version 3.5.0) --
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 COMPLEX*16 A( LDA, * ), B( LDB, * )
153 * =====================================================================
157 PARAMETER ( ONE = ( 1.0D+0, 0.0D+0 ) )
159 * .. Local Scalars ..
163 COMPLEX*16 AK, AKM1, AKM1K, BK, BKM1, DENOM
165 * .. External Functions ..
169 * .. External Subroutines ..
170 EXTERNAL ZGEMV, ZGERU, ZLACGV, ZDSCAL, ZSWAP, XERBLA
172 * .. Intrinsic Functions ..
173 INTRINSIC DCONJG, MAX, DBLE
175 * .. Executable Statements ..
178 UPPER = LSAME( UPLO, 'U' )
179 IF( .NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
181 ELSE IF( N.LT.0 ) THEN
183 ELSE IF( NRHS.LT.0 ) THEN
185 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
187 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
191 CALL XERBLA( 'ZHETRS_ROOK', -INFO )
195 * Quick return if possible
197 IF( N.EQ.0 .OR. NRHS.EQ.0 )
202 * Solve A*X = B, where A = U*D*U**H.
204 * First solve U*D*X = B, overwriting B with X.
206 * K is the main loop index, decreasing from N to 1 in steps of
207 * 1 or 2, depending on the size of the diagonal blocks.
212 * If K < 1, exit from loop.
217 IF( IPIV( K ).GT.0 ) THEN
219 * 1 x 1 diagonal block
221 * Interchange rows K and IPIV(K).
225 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
227 * Multiply by inv(U(K)), where U(K) is the transformation
228 * stored in column K of A.
230 CALL ZGERU( K-1, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,
233 * Multiply by the inverse of the diagonal block.
235 S = DBLE( ONE ) / DBLE( A( K, K ) )
236 CALL ZDSCAL( NRHS, S, B( K, 1 ), LDB )
240 * 2 x 2 diagonal block
242 * Interchange rows K and -IPIV(K), then K-1 and -IPIV(K-1)
246 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
250 $ CALL ZSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )
252 * Multiply by inv(U(K)), where U(K) is the transformation
253 * stored in columns K-1 and K of A.
255 CALL ZGERU( K-2, NRHS, -ONE, A( 1, K ), 1, B( K, 1 ), LDB,
257 CALL ZGERU( K-2, NRHS, -ONE, A( 1, K-1 ), 1, B( K-1, 1 ),
258 $ 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 ) / DCONJG( AKM1K )
265 DENOM = AKM1*AK - ONE
267 BKM1 = B( K-1, J ) / AKM1K
268 BK = B( K, J ) / DCONJG( AKM1K )
269 B( K-1, J ) = ( AK*BKM1-BK ) / DENOM
270 B( K, J ) = ( AKM1*BK-BKM1 ) / DENOM
278 * Next solve U**H *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**H(K)), where U(K) is the transformation
296 * stored in column K of A.
299 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
300 CALL ZGEMV( 'Conjugate transpose', K-1, NRHS, -ONE, B,
301 $ LDB, A( 1, K ), 1, ONE, B( K, 1 ), LDB )
302 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
305 * Interchange rows K and IPIV(K).
309 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
313 * 2 x 2 diagonal block
315 * Multiply by inv(U**H(K+1)), where U(K+1) is the transformation
316 * stored in columns K and K+1 of A.
319 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
320 CALL ZGEMV( 'Conjugate transpose', K-1, NRHS, -ONE, B,
321 $ LDB, A( 1, K ), 1, ONE, B( K, 1 ), LDB )
322 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
324 CALL ZLACGV( NRHS, B( K+1, 1 ), LDB )
325 CALL ZGEMV( 'Conjugate transpose', K-1, NRHS, -ONE, B,
326 $ LDB, A( 1, K+1 ), 1, ONE, B( K+1, 1 ), LDB )
327 CALL ZLACGV( NRHS, B( K+1, 1 ), LDB )
330 * Interchange rows K and -IPIV(K), then K+1 and -IPIV(K+1)
334 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
338 $ CALL ZSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )
348 * Solve A*X = B, where A = L*D*L**H.
350 * First solve L*D*X = B, overwriting B with X.
352 * K is the main loop index, increasing from 1 to N in steps of
353 * 1 or 2, depending on the size of the diagonal blocks.
358 * If K > N, exit from loop.
363 IF( IPIV( K ).GT.0 ) THEN
365 * 1 x 1 diagonal block
367 * Interchange rows K and IPIV(K).
371 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
373 * Multiply by inv(L(K)), where L(K) is the transformation
374 * stored in column K of A.
377 $ CALL ZGERU( N-K, NRHS, -ONE, A( K+1, K ), 1, B( K, 1 ),
378 $ LDB, B( K+1, 1 ), LDB )
380 * Multiply by the inverse of the diagonal block.
382 S = DBLE( ONE ) / DBLE( A( K, K ) )
383 CALL ZDSCAL( NRHS, S, B( K, 1 ), LDB )
387 * 2 x 2 diagonal block
389 * Interchange rows K and -IPIV(K), then K+1 and -IPIV(K+1)
393 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
397 $ CALL ZSWAP( NRHS, B( K+1, 1 ), LDB, B( KP, 1 ), LDB )
399 * Multiply by inv(L(K)), where L(K) is the transformation
400 * stored in columns K and K+1 of A.
403 CALL ZGERU( N-K-1, NRHS, -ONE, A( K+2, K ), 1, B( K, 1 ),
404 $ LDB, B( K+2, 1 ), LDB )
405 CALL ZGERU( N-K-1, NRHS, -ONE, A( K+2, K+1 ), 1,
406 $ B( K+1, 1 ), LDB, B( K+2, 1 ), LDB )
409 * Multiply by the inverse of the diagonal block.
412 AKM1 = A( K, K ) / DCONJG( AKM1K )
413 AK = A( K+1, K+1 ) / AKM1K
414 DENOM = AKM1*AK - ONE
416 BKM1 = B( K, J ) / DCONJG( AKM1K )
417 BK = B( K+1, J ) / AKM1K
418 B( K, J ) = ( AK*BKM1-BK ) / DENOM
419 B( K+1, J ) = ( AKM1*BK-BKM1 ) / DENOM
427 * Next solve L**H *X = B, overwriting B with X.
429 * K is the main loop index, decreasing from N to 1 in steps of
430 * 1 or 2, depending on the size of the diagonal blocks.
435 * If K < 1, exit from loop.
440 IF( IPIV( K ).GT.0 ) THEN
442 * 1 x 1 diagonal block
444 * Multiply by inv(L**H(K)), where L(K) is the transformation
445 * stored in column K of A.
448 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
449 CALL ZGEMV( 'Conjugate transpose', N-K, NRHS, -ONE,
450 $ B( K+1, 1 ), LDB, A( K+1, K ), 1, ONE,
452 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
455 * Interchange rows K and IPIV(K).
459 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
463 * 2 x 2 diagonal block
465 * Multiply by inv(L**H(K-1)), where L(K-1) is the transformation
466 * stored in columns K-1 and K of A.
469 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
470 CALL ZGEMV( 'Conjugate transpose', N-K, NRHS, -ONE,
471 $ B( K+1, 1 ), LDB, A( K+1, K ), 1, ONE,
473 CALL ZLACGV( NRHS, B( K, 1 ), LDB )
475 CALL ZLACGV( NRHS, B( K-1, 1 ), LDB )
476 CALL ZGEMV( 'Conjugate transpose', N-K, NRHS, -ONE,
477 $ B( K+1, 1 ), LDB, A( K+1, K-1 ), 1, ONE,
479 CALL ZLACGV( NRHS, B( K-1, 1 ), LDB )
482 * Interchange rows K and -IPIV(K), then K-1 and -IPIV(K-1)
486 $ CALL ZSWAP( NRHS, B( K, 1 ), LDB, B( KP, 1 ), LDB )
490 $ CALL ZSWAP( NRHS, B( K-1, 1 ), LDB, B( KP, 1 ), LDB )