LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
zsytrf_aa.f
Go to the documentation of this file.
1*> \brief \b ZSYTRF_AA
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download ZSYTRF_AA + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zsytrf_aa.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zsytrf_aa.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zsytrf_aa.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE ZSYTRF_AA( UPLO, N, A, LDA, IPIV, WORK, LWORK, INFO )
20*
21* .. Scalar Arguments ..
22* CHARACTER UPLO
23* INTEGER N, LDA, LWORK, INFO
24* ..
25* .. Array Arguments ..
26* INTEGER IPIV( * )
27* COMPLEX*16 A( LDA, * ), WORK( * )
28* ..
29*
30*> \par Purpose:
31* =============
32*>
33*> \verbatim
34*>
35*> ZSYTRF_AA computes the factorization of a complex symmetric matrix A
36*> using the Aasen's algorithm. The form of the factorization is
37*>
38*> A = U**T*T*U or A = L*T*L**T
39*>
40*> where U (or L) is a product of permutation and unit upper (lower)
41*> triangular matrices, and T is a complex symmetric tridiagonal matrix.
42*>
43*> This is the blocked version of the algorithm, calling Level 3 BLAS.
44*> \endverbatim
45*
46* Arguments:
47* ==========
48*
49*> \param[in] UPLO
50*> \verbatim
51*> UPLO is CHARACTER*1
52*> = 'U': Upper triangle of A is stored;
53*> = 'L': Lower triangle of A is stored.
54*> \endverbatim
55*>
56*> \param[in] N
57*> \verbatim
58*> N is INTEGER
59*> The order of the matrix A. N >= 0.
60*> \endverbatim
61*>
62*> \param[in,out] A
63*> \verbatim
64*> A is COMPLEX*16 array, dimension (LDA,N)
65*> On entry, the symmetric matrix A. If UPLO = 'U', the leading
66*> N-by-N upper triangular part of A contains the upper
67*> triangular part of the matrix A, and the strictly lower
68*> triangular part of A is not referenced. If UPLO = 'L', the
69*> leading N-by-N lower triangular part of A contains the lower
70*> triangular part of the matrix A, and the strictly upper
71*> triangular part of A is not referenced.
72*>
73*> On exit, the tridiagonal matrix is stored in the diagonals
74*> and the subdiagonals of A just below (or above) the diagonals,
75*> and L is stored below (or above) the subdiagonals, when UPLO
76*> is 'L' (or 'U').
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[out] IPIV
86*> \verbatim
87*> IPIV is INTEGER array, dimension (N)
88*> On exit, it contains the details of the interchanges, i.e.,
89*> the row and column k of A were interchanged with the
90*> row and column IPIV(k).
91*> \endverbatim
92*>
93*> \param[out] WORK
94*> \verbatim
95*> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
96*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
97*> \endverbatim
98*>
99*> \param[in] LWORK
100*> \verbatim
101*> LWORK is INTEGER
102*> The length of WORK. LWORK >=MAX(1,2*N). For optimum performance
103*> LWORK >= N*(1+NB), where NB is the optimal blocksize.
104*>
105*> If LWORK = -1, then a workspace query is assumed; the routine
106*> only calculates the optimal size of the WORK array, returns
107*> this value as the first entry of the WORK array, and no error
108*> message related to LWORK is issued by XERBLA.
109*> \endverbatim
110*>
111*> \param[out] INFO
112*> \verbatim
113*> INFO is INTEGER
114*> = 0: successful exit
115*> < 0: if INFO = -i, the i-th argument had an illegal value.
116*> \endverbatim
117*
118* Authors:
119* ========
120*
121*> \author Univ. of Tennessee
122*> \author Univ. of California Berkeley
123*> \author Univ. of Colorado Denver
124*> \author NAG Ltd.
125*
126*> \ingroup hetrf_aa
127*
128* =====================================================================
129 SUBROUTINE zsytrf_aa( UPLO, N, A, LDA, IPIV, WORK, LWORK, 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 IMPLICIT NONE
136*
137* .. Scalar Arguments ..
138 CHARACTER UPLO
139 INTEGER N, LDA, LWORK, INFO
140* ..
141* .. Array Arguments ..
142 INTEGER IPIV( * )
143 COMPLEX*16 A( LDA, * ), WORK( * )
144* ..
145*
146* =====================================================================
147* .. Parameters ..
148 COMPLEX*16 ZERO, ONE
149 parameter( zero = 0.0d+0, one = 1.0d+0 )
150*
151* .. Local Scalars ..
152 LOGICAL LQUERY, UPPER
153 INTEGER J, LWKOPT
154 INTEGER NB, MJ, NJ, K1, K2, J1, J2, J3, JB
155 COMPLEX*16 ALPHA
156* ..
157* .. External Functions ..
158 LOGICAL LSAME
159 INTEGER ILAENV
160 EXTERNAL lsame, ilaenv
161* ..
162* .. External Subroutines ..
163 EXTERNAL zlasyf_aa, zgemm, zgemv, zscal,
164 $ zcopy,
165 $ zswap, xerbla
166* ..
167* .. Intrinsic Functions ..
168 INTRINSIC max
169* ..
170* .. Executable Statements ..
171*
172* Determine the block size
173*
174 nb = ilaenv( 1, 'ZSYTRF_AA', uplo, n, -1, -1, -1 )
175*
176* Test the input parameters.
177*
178 info = 0
179 upper = lsame( uplo, 'U' )
180 lquery = ( lwork.EQ.-1 )
181 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
182 info = -1
183 ELSE IF( n.LT.0 ) THEN
184 info = -2
185 ELSE IF( lda.LT.max( 1, n ) ) THEN
186 info = -4
187 ELSE IF( lwork.LT.max( 1, 2*n ) .AND. .NOT.lquery ) THEN
188 info = -7
189 END IF
190*
191 IF( info.EQ.0 ) THEN
192 lwkopt = (nb+1)*n
193 work( 1 ) = lwkopt
194 END IF
195*
196 IF( info.NE.0 ) THEN
197 CALL xerbla( 'ZSYTRF_AA', -info )
198 RETURN
199 ELSE IF( lquery ) THEN
200 RETURN
201 END IF
202*
203* Quick return
204*
205 IF ( n.EQ.0 ) THEN
206 RETURN
207 ENDIF
208 ipiv( 1 ) = 1
209 IF ( n.EQ.1 ) THEN
210 RETURN
211 END IF
212*
213* Adjust block size based on the workspace size
214*
215 IF( lwork.LT.((1+nb)*n) ) THEN
216 nb = ( lwork-n ) / n
217 END IF
218*
219 IF( upper ) THEN
220*
221* .....................................................
222* Factorize A as U**T*D*U using the upper triangle of A
223* .....................................................
224*
225* Copy first row A(1, 1:N) into H(1:n) (stored in WORK(1:N))
226*
227 CALL zcopy( n, a( 1, 1 ), lda, work( 1 ), 1 )
228*
229* J is the main loop index, increasing from 1 to N in steps of
230* JB, where JB is the number of columns factorized by ZLASYF;
231* JB is either NB, or N-J+1 for the last block
232*
233 j = 0
234 10 CONTINUE
235 IF( j.GE.n )
236 $ GO TO 20
237*
238* each step of the main loop
239* J is the last column of the previous panel
240* J1 is the first column of the current panel
241* K1 identifies if the previous column of the panel has been
242* explicitly stored, e.g., K1=1 for the first panel, and
243* K1=0 for the rest
244*
245 j1 = j + 1
246 jb = min( n-j1+1, nb )
247 k1 = max(1, j)-j
248*
249* Panel factorization
250*
251 CALL zlasyf_aa( uplo, 2-k1, n-j, jb,
252 $ a( max(1, j), j+1 ), lda,
253 $ ipiv( j+1 ), work, n, work( n*nb+1 ) )
254*
255* Adjust IPIV and apply it back (J-th step picks (J+1)-th pivot)
256*
257 DO j2 = j+2, min(n, j+jb+1)
258 ipiv( j2 ) = ipiv( j2 ) + j
259 IF( (j2.NE.ipiv(j2)) .AND. ((j1-k1).GT.2) ) THEN
260 CALL zswap( j1-k1-2, a( 1, j2 ), 1,
261 $ a( 1, ipiv(j2) ), 1 )
262 END IF
263 END DO
264 j = j + jb
265*
266* Trailing submatrix update, where
267* the row A(J1-1, J2-1:N) stores U(J1, J2+1:N) and
268* WORK stores the current block of the auxiriarly matrix H
269*
270 IF( j.LT.n ) THEN
271*
272* If first panel and JB=1 (NB=1), then nothing to do
273*
274 IF( j1.GT.1 .OR. jb.GT.1 ) THEN
275*
276* Merge rank-1 update with BLAS-3 update
277*
278 alpha = a( j, j+1 )
279 a( j, j+1 ) = one
280 CALL zcopy( n-j, a( j-1, j+1 ), lda,
281 $ work( (j+1-j1+1)+jb*n ), 1 )
282 CALL zscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1 )
283*
284* K1 identifies if the previous column of the panel has been
285* explicitly stored, e.g., K1=1 and K2= 0 for the first panel,
286* while K1=0 and K2=1 for the rest
287*
288 IF( j1.GT.1 ) THEN
289*
290* Not first panel
291*
292 k2 = 1
293 ELSE
294*
295* First panel
296*
297 k2 = 0
298*
299* First update skips the first column
300*
301 jb = jb - 1
302 END IF
303*
304 DO j2 = j+1, n, nb
305 nj = min( nb, n-j2+1 )
306*
307* Update (J2, J2) diagonal block with ZGEMV
308*
309 j3 = j2
310 DO mj = nj-1, 1, -1
311 CALL zgemv( 'No transpose', mj, jb+1,
312 $ -one, work( j3-j1+1+k1*n ), n,
313 $ a( j1-k2, j3 ), 1,
314 $ one, a( j3, j3 ), lda )
315 j3 = j3 + 1
316 END DO
317*
318* Update off-diagonal block of J2-th block row with ZGEMM
319*
320 CALL zgemm( 'Transpose', 'Transpose',
321 $ nj, n-j3+1, jb+1,
322 $ -one, a( j1-k2, j2 ), lda,
323 $ work( j3-j1+1+k1*n ), n,
324 $ one, a( j2, j3 ), lda )
325 END DO
326*
327* Recover T( J, J+1 )
328*
329 a( j, j+1 ) = alpha
330 END IF
331*
332* WORK(J+1, 1) stores H(J+1, 1)
333*
334 CALL zcopy( n-j, a( j+1, j+1 ), lda, work( 1 ), 1 )
335 END IF
336 GO TO 10
337 ELSE
338*
339* .....................................................
340* Factorize A as L*D*L**T using the lower triangle of A
341* .....................................................
342*
343* copy first column A(1:N, 1) into H(1:N, 1)
344* (stored in WORK(1:N))
345*
346 CALL zcopy( n, a( 1, 1 ), 1, work( 1 ), 1 )
347*
348* J is the main loop index, increasing from 1 to N in steps of
349* JB, where JB is the number of columns factorized by ZLASYF;
350* JB is either NB, or N-J+1 for the last block
351*
352 j = 0
353 11 CONTINUE
354 IF( j.GE.n )
355 $ GO TO 20
356*
357* each step of the main loop
358* J is the last column of the previous panel
359* J1 is the first column of the current panel
360* K1 identifies if the previous column of the panel has been
361* explicitly stored, e.g., K1=1 for the first panel, and
362* K1=0 for the rest
363*
364 j1 = j+1
365 jb = min( n-j1+1, nb )
366 k1 = max(1, j)-j
367*
368* Panel factorization
369*
370 CALL zlasyf_aa( uplo, 2-k1, n-j, jb,
371 $ a( j+1, max(1, j) ), lda,
372 $ ipiv( j+1 ), work, n, work( n*nb+1 ) )
373*
374* Adjust IPIV and apply it back (J-th step picks (J+1)-th pivot)
375*
376 DO j2 = j+2, min(n, j+jb+1)
377 ipiv( j2 ) = ipiv( j2 ) + j
378 IF( (j2.NE.ipiv(j2)) .AND. ((j1-k1).GT.2) ) THEN
379 CALL zswap( j1-k1-2, a( j2, 1 ), lda,
380 $ a( ipiv(j2), 1 ), lda )
381 END IF
382 END DO
383 j = j + jb
384*
385* Trailing submatrix update, where
386* A(J2+1, J1-1) stores L(J2+1, J1) and
387* WORK(J2+1, 1) stores H(J2+1, 1)
388*
389 IF( j.LT.n ) THEN
390*
391* if first panel and JB=1 (NB=1), then nothing to do
392*
393 IF( j1.GT.1 .OR. jb.GT.1 ) THEN
394*
395* Merge rank-1 update with BLAS-3 update
396*
397 alpha = a( j+1, j )
398 a( j+1, j ) = one
399 CALL zcopy( n-j, a( j+1, j-1 ), 1,
400 $ work( (j+1-j1+1)+jb*n ), 1 )
401 CALL zscal( n-j, alpha, work( (j+1-j1+1)+jb*n ), 1 )
402*
403* K1 identifies if the previous column of the panel has been
404* explicitly stored, e.g., K1=1 and K2= 0 for the first panel,
405* while K1=0 and K2=1 for the rest
406*
407 IF( j1.GT.1 ) THEN
408*
409* Not first panel
410*
411 k2 = 1
412 ELSE
413*
414* First panel
415*
416 k2 = 0
417*
418* First update skips the first column
419*
420 jb = jb - 1
421 END IF
422*
423 DO j2 = j+1, n, nb
424 nj = min( nb, n-j2+1 )
425*
426* Update (J2, J2) diagonal block with ZGEMV
427*
428 j3 = j2
429 DO mj = nj-1, 1, -1
430 CALL zgemv( 'No transpose', mj, jb+1,
431 $ -one, work( j3-j1+1+k1*n ), n,
432 $ a( j3, j1-k2 ), lda,
433 $ one, a( j3, j3 ), 1 )
434 j3 = j3 + 1
435 END DO
436*
437* Update off-diagonal block in J2-th block column with ZGEMM
438*
439 CALL zgemm( 'No transpose', 'Transpose',
440 $ n-j3+1, nj, jb+1,
441 $ -one, work( j3-j1+1+k1*n ), n,
442 $ a( j2, j1-k2 ), lda,
443 $ one, a( j3, j2 ), lda )
444 END DO
445*
446* Recover T( J+1, J )
447*
448 a( j+1, j ) = alpha
449 END IF
450*
451* WORK(J+1, 1) stores H(J+1, 1)
452*
453 CALL zcopy( n-j, a( j+1, j+1 ), 1, work( 1 ), 1 )
454 END IF
455 GO TO 11
456 END IF
457*
458 20 CONTINUE
459 work( 1 ) = lwkopt
460 RETURN
461*
462* End of ZSYTRF_AA
463*
464 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine zcopy(n, zx, incx, zy, incy)
ZCOPY
Definition zcopy.f:81
subroutine zgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
ZGEMM
Definition zgemm.f:188
subroutine zgemv(trans, m, n, alpha, a, lda, x, incx, beta, y, incy)
ZGEMV
Definition zgemv.f:160
subroutine zsytrf_aa(uplo, n, a, lda, ipiv, work, lwork, info)
ZSYTRF_AA
Definition zsytrf_aa.f:130
subroutine zlasyf_aa(uplo, j1, m, nb, a, lda, ipiv, h, ldh, work)
ZLASYF_AA
Definition zlasyf_aa.f:142
subroutine zscal(n, za, zx, incx)
ZSCAL
Definition zscal.f:78
subroutine zswap(n, zx, incx, zy, incy)
ZSWAP
Definition zswap.f:81