LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
zsytrs2.f
Go to the documentation of this file.
1*> \brief \b ZSYTRS2
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download ZSYTRS2 + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zsytrs2.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zsytrs2.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytrs2.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE ZSYTRS2( UPLO, N, NRHS, A, LDA, IPIV, B, LDB,
20* WORK, INFO )
21*
22* .. Scalar Arguments ..
23* CHARACTER UPLO
24* INTEGER INFO, LDA, LDB, N, NRHS
25* ..
26* .. Array Arguments ..
27* INTEGER IPIV( * )
28* COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
29* ..
30*
31*
32*> \par Purpose:
33* =============
34*>
35*> \verbatim
36*>
37*> ZSYTRS2 solves a system of linear equations A*X = B with a complex
38*> symmetric matrix A using the factorization A = U*D*U**T or
39*> A = L*D*L**T computed by ZSYTRF and converted by ZSYCONV.
40*> \endverbatim
41*
42* Arguments:
43* ==========
44*
45*> \param[in] UPLO
46*> \verbatim
47*> UPLO is CHARACTER*1
48*> Specifies whether the details of the factorization are stored
49*> as an upper or lower triangular matrix.
50*> = 'U': Upper triangular, form is A = U*D*U**T;
51*> = 'L': Lower triangular, form is A = L*D*L**T.
52*> \endverbatim
53*>
54*> \param[in] N
55*> \verbatim
56*> N is INTEGER
57*> The order of the matrix A. N >= 0.
58*> \endverbatim
59*>
60*> \param[in] NRHS
61*> \verbatim
62*> NRHS is INTEGER
63*> The number of right hand sides, i.e., the number of columns
64*> of the matrix B. NRHS >= 0.
65*> \endverbatim
66*>
67*> \param[in,out] A
68*> \verbatim
69*> A is COMPLEX*16 array, dimension (LDA,N)
70*> The block diagonal matrix D and the multipliers used to
71*> obtain the factor U or L as computed by ZSYTRF.
72*> Note that A is input / output. This might be counter-intuitive,
73*> and one may think that A is input only. A is input / output. This
74*> is because, at the start of the subroutine, we permute A in a
75*> "better" form and then we permute A back to its original form at
76*> the end.
77*> \endverbatim
78*>
79*> \param[in] LDA
80*> \verbatim
81*> LDA is INTEGER
82*> The leading dimension of the array A. LDA >= max(1,N).
83*> \endverbatim
84*>
85*> \param[in] IPIV
86*> \verbatim
87*> IPIV is INTEGER array, dimension (N)
88*> Details of the interchanges and the block structure of D
89*> as determined by ZSYTRF.
90*> \endverbatim
91*>
92*> \param[in,out] B
93*> \verbatim
94*> B is COMPLEX*16 array, dimension (LDB,NRHS)
95*> On entry, the right hand side matrix B.
96*> On exit, the solution matrix X.
97*> \endverbatim
98*>
99*> \param[in] LDB
100*> \verbatim
101*> LDB is INTEGER
102*> The leading dimension of the array B. LDB >= max(1,N).
103*> \endverbatim
104*>
105*> \param[out] WORK
106*> \verbatim
107*> WORK is COMPLEX*16 array, dimension (N)
108*> \endverbatim
109*>
110*> \param[out] INFO
111*> \verbatim
112*> INFO is INTEGER
113*> = 0: successful exit
114*> < 0: if INFO = -i, the i-th argument had an illegal value
115*> \endverbatim
116*
117* Authors:
118* ========
119*
120*> \author Univ. of Tennessee
121*> \author Univ. of California Berkeley
122*> \author Univ. of Colorado Denver
123*> \author NAG Ltd.
124*
125*> \ingroup hetrs2
126*
127* =====================================================================
128 SUBROUTINE zsytrs2( UPLO, N, NRHS, A, LDA, IPIV, B, LDB,
129 $ WORK, INFO )
130*
131* -- LAPACK computational routine --
132* -- LAPACK is a software package provided by Univ. of Tennessee, --
133* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
134*
135* .. Scalar Arguments ..
136 CHARACTER UPLO
137 INTEGER INFO, LDA, LDB, N, NRHS
138* ..
139* .. Array Arguments ..
140 INTEGER IPIV( * )
141 COMPLEX*16 A( LDA, * ), B( LDB, * ), WORK( * )
142* ..
143*
144* =====================================================================
145*
146* .. Parameters ..
147 COMPLEX*16 ONE
148 parameter( one = (1.0d+0,0.0d+0) )
149* ..
150* .. Local Scalars ..
151 LOGICAL UPPER
152 INTEGER I, IINFO, J, K, KP
153 COMPLEX*16 AK, AKM1, AKM1K, BK, BKM1, DENOM
154* ..
155* .. External Functions ..
156 LOGICAL LSAME
157 EXTERNAL lsame
158* ..
159* .. External Subroutines ..
160 EXTERNAL zscal, zsyconv, zswap, ztrsm,
161 $ xerbla
162* ..
163* .. Intrinsic Functions ..
164 INTRINSIC max
165* ..
166* .. Executable Statements ..
167*
168 info = 0
169 upper = lsame( uplo, 'U' )
170 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
171 info = -1
172 ELSE IF( n.LT.0 ) THEN
173 info = -2
174 ELSE IF( nrhs.LT.0 ) THEN
175 info = -3
176 ELSE IF( lda.LT.max( 1, n ) ) THEN
177 info = -5
178 ELSE IF( ldb.LT.max( 1, n ) ) THEN
179 info = -8
180 END IF
181 IF( info.NE.0 ) THEN
182 CALL xerbla( 'ZSYTRS2', -info )
183 RETURN
184 END IF
185*
186* Quick return if possible
187*
188 IF( n.EQ.0 .OR. nrhs.EQ.0 )
189 $ RETURN
190*
191* Convert A
192*
193 CALL zsyconv( uplo, 'C', n, a, lda, ipiv, work, iinfo )
194*
195 IF( upper ) THEN
196*
197* Solve A*X = B, where A = U*D*U**T.
198*
199* P**T * B
200 k=n
201 DO WHILE ( k .GE. 1 )
202 IF( ipiv( k ).GT.0 ) THEN
203* 1 x 1 diagonal block
204* Interchange rows K and IPIV(K).
205 kp = ipiv( k )
206 IF( kp.NE.k )
207 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
208 k=k-1
209 ELSE
210* 2 x 2 diagonal block
211* Interchange rows K-1 and -IPIV(K).
212 kp = -ipiv( k )
213 IF( kp.EQ.-ipiv( k-1 ) )
214 $ CALL zswap( nrhs, b( k-1, 1 ), ldb, b( kp, 1 ), ldb )
215 k=k-2
216 END IF
217 END DO
218*
219* Compute (U \P**T * B) -> B [ (U \P**T * B) ]
220*
221 CALL ztrsm('L','U','N','U',n,nrhs,one,a,lda,b,ldb)
222*
223* Compute D \ B -> B [ D \ (U \P**T * B) ]
224*
225 i=n
226 DO WHILE ( i .GE. 1 )
227 IF( ipiv(i) .GT. 0 ) THEN
228 CALL zscal( nrhs, one / a( i, i ), b( i, 1 ), ldb )
229 ELSEIF ( i .GT. 1) THEN
230 IF ( ipiv(i-1) .EQ. ipiv(i) ) THEN
231 akm1k = work(i)
232 akm1 = a( i-1, i-1 ) / akm1k
233 ak = a( i, i ) / akm1k
234 denom = akm1*ak - one
235 DO 15 j = 1, nrhs
236 bkm1 = b( i-1, j ) / akm1k
237 bk = b( i, j ) / akm1k
238 b( i-1, j ) = ( ak*bkm1-bk ) / denom
239 b( i, j ) = ( akm1*bk-bkm1 ) / denom
240 15 CONTINUE
241 i = i - 1
242 ENDIF
243 ENDIF
244 i = i - 1
245 END DO
246*
247* Compute (U**T \ B) -> B [ U**T \ (D \ (U \P**T * B) ) ]
248*
249 CALL ztrsm('L','U','T','U',n,nrhs,one,a,lda,b,ldb)
250*
251* P * B [ P * (U**T \ (D \ (U \P**T * B) )) ]
252*
253 k=1
254 DO WHILE ( k .LE. n )
255 IF( ipiv( k ).GT.0 ) THEN
256* 1 x 1 diagonal block
257* Interchange rows K and IPIV(K).
258 kp = ipiv( k )
259 IF( kp.NE.k )
260 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
261 k=k+1
262 ELSE
263* 2 x 2 diagonal block
264* Interchange rows K-1 and -IPIV(K).
265 kp = -ipiv( k )
266 IF( k .LT. n .AND. kp.EQ.-ipiv( k+1 ) )
267 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
268 k=k+2
269 ENDIF
270 END DO
271*
272 ELSE
273*
274* Solve A*X = B, where A = L*D*L**T.
275*
276* P**T * B
277 k=1
278 DO WHILE ( k .LE. n )
279 IF( ipiv( k ).GT.0 ) THEN
280* 1 x 1 diagonal block
281* Interchange rows K and IPIV(K).
282 kp = ipiv( k )
283 IF( kp.NE.k )
284 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
285 k=k+1
286 ELSE
287* 2 x 2 diagonal block
288* Interchange rows K and -IPIV(K+1).
289 kp = -ipiv( k+1 )
290 IF( kp.EQ.-ipiv( k ) )
291 $ CALL zswap( nrhs, b( k+1, 1 ), ldb, b( kp, 1 ), ldb )
292 k=k+2
293 ENDIF
294 END DO
295*
296* Compute (L \P**T * B) -> B [ (L \P**T * B) ]
297*
298 CALL ztrsm('L','L','N','U',n,nrhs,one,a,lda,b,ldb)
299*
300* Compute D \ B -> B [ D \ (L \P**T * B) ]
301*
302 i=1
303 DO WHILE ( i .LE. n )
304 IF( ipiv(i) .GT. 0 ) THEN
305 CALL zscal( nrhs, one / a( i, i ), b( i, 1 ), ldb )
306 ELSE
307 akm1k = work(i)
308 akm1 = a( i, i ) / akm1k
309 ak = a( i+1, i+1 ) / akm1k
310 denom = akm1*ak - one
311 DO 25 j = 1, nrhs
312 bkm1 = b( i, j ) / akm1k
313 bk = b( i+1, j ) / akm1k
314 b( i, j ) = ( ak*bkm1-bk ) / denom
315 b( i+1, j ) = ( akm1*bk-bkm1 ) / denom
316 25 CONTINUE
317 i = i + 1
318 ENDIF
319 i = i + 1
320 END DO
321*
322* Compute (L**T \ B) -> B [ L**T \ (D \ (L \P**T * B) ) ]
323*
324 CALL ztrsm('L','L','T','U',n,nrhs,one,a,lda,b,ldb)
325*
326* P * B [ P * (L**T \ (D \ (L \P**T * B) )) ]
327*
328 k=n
329 DO WHILE ( k .GE. 1 )
330 IF( ipiv( k ).GT.0 ) THEN
331* 1 x 1 diagonal block
332* Interchange rows K and IPIV(K).
333 kp = ipiv( k )
334 IF( kp.NE.k )
335 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
336 k=k-1
337 ELSE
338* 2 x 2 diagonal block
339* Interchange rows K-1 and -IPIV(K).
340 kp = -ipiv( k )
341 IF( k.GT.1 .AND. kp.EQ.-ipiv( k-1 ) )
342 $ CALL zswap( nrhs, b( k, 1 ), ldb, b( kp, 1 ), ldb )
343 k=k-2
344 ENDIF
345 END DO
346*
347 END IF
348*
349* Revert A
350*
351 CALL zsyconv( uplo, 'R', n, a, lda, ipiv, work, iinfo )
352*
353 RETURN
354*
355* End of ZSYTRS2
356*
357 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zsytrs2(uplo, n, nrhs, a, lda, ipiv, b, ldb, work, info)
ZSYTRS2
Definition zsytrs2.f:130
subroutine zscal(n, za, zx, incx)
ZSCAL
Definition zscal.f:78
subroutine zswap(n, zx, incx, zy, incy)
ZSWAP
Definition zswap.f:81
subroutine zsyconv(uplo, way, n, a, lda, ipiv, e, info)
ZSYCONV
Definition zsyconv.f:112
subroutine ztrsm(side, uplo, transa, diag, m, n, alpha, a, lda, b, ldb)
ZTRSM
Definition ztrsm.f:180