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