LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
csytf2.f
Go to the documentation of this file.
1*> \brief \b CSYTF2 computes the factorization of a real symmetric indefinite matrix, using the diagonal pivoting method (unblocked algorithm).
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download CSYTF2 + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/csytf2.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/csytf2.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/csytf2.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE CSYTF2( UPLO, N, A, LDA, IPIV, INFO )
20*
21* .. Scalar Arguments ..
22* CHARACTER UPLO
23* INTEGER INFO, LDA, N
24* ..
25* .. Array Arguments ..
26* INTEGER IPIV( * )
27* COMPLEX A( LDA, * )
28* ..
29*
30*
31*> \par Purpose:
32* =============
33*>
34*> \verbatim
35*>
36*> CSYTF2 computes the factorization of a complex symmetric matrix A
37*> using the Bunch-Kaufman diagonal pivoting method:
38*>
39*> A = U*D*U**T or A = L*D*L**T
40*>
41*> where U (or L) is a product of permutation and unit upper (lower)
42*> triangular matrices, U**T is the transpose of U, and D is symmetric and
43*> block diagonal with 1-by-1 and 2-by-2 diagonal blocks.
44*>
45*> This is the unblocked version of the algorithm, calling Level 2 BLAS.
46*> \endverbatim
47*
48* Arguments:
49* ==========
50*
51*> \param[in] UPLO
52*> \verbatim
53*> UPLO is CHARACTER*1
54*> Specifies whether the upper or lower triangular part of the
55*> symmetric matrix A is stored:
56*> = 'U': Upper triangular
57*> = 'L': Lower triangular
58*> \endverbatim
59*>
60*> \param[in] N
61*> \verbatim
62*> N is INTEGER
63*> The order of the matrix A. N >= 0.
64*> \endverbatim
65*>
66*> \param[in,out] A
67*> \verbatim
68*> A is COMPLEX array, dimension (LDA,N)
69*> On entry, the symmetric matrix A. If UPLO = 'U', the leading
70*> n-by-n upper triangular part of A contains the upper
71*> triangular part of the matrix A, and the strictly lower
72*> triangular part of A is not referenced. If UPLO = 'L', the
73*> leading n-by-n lower triangular part of A contains the lower
74*> triangular part of the matrix A, and the strictly upper
75*> triangular part of A is not referenced.
76*>
77*> On exit, the block diagonal matrix D and the multipliers used
78*> to obtain the factor U or L (see below for further details).
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*> Details of the interchanges and the block structure of D.
91*>
92*> If UPLO = 'U':
93*> If IPIV(k) > 0, then rows and columns k and IPIV(k) were
94*> interchanged and D(k,k) is a 1-by-1 diagonal block.
95*>
96*> If IPIV(k) = IPIV(k-1) < 0, then rows and columns
97*> k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k)
98*> is a 2-by-2 diagonal block.
99*>
100*> If UPLO = 'L':
101*> If IPIV(k) > 0, then rows and columns k and IPIV(k) were
102*> interchanged and D(k,k) is a 1-by-1 diagonal block.
103*>
104*> If IPIV(k) = IPIV(k+1) < 0, then rows and columns
105*> k+1 and -IPIV(k) were interchanged and D(k:k+1,k:k+1)
106*> is a 2-by-2 diagonal block.
107*> \endverbatim
108*>
109*> \param[out] INFO
110*> \verbatim
111*> INFO is INTEGER
112*> = 0: successful exit
113*> < 0: if INFO = -k, the k-th argument had an illegal value
114*> > 0: if INFO = k, D(k,k) is exactly zero. The factorization
115*> has been completed, but the block diagonal matrix D is
116*> exactly singular, and division by zero will occur if it
117*> is used to solve a system of equations.
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 hetf2
129*
130*> \par Further Details:
131* =====================
132*>
133*> \verbatim
134*>
135*> If UPLO = 'U', then A = U*D*U**T, where
136*> U = P(n)*U(n)* ... *P(k)U(k)* ...,
137*> i.e., U is a product of terms P(k)*U(k), where k decreases from n to
138*> 1 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
139*> and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as
140*> defined by IPIV(k), and U(k) is a unit upper triangular matrix, such
141*> that if the diagonal block D(k) is of order s (s = 1 or 2), then
142*>
143*> ( I v 0 ) k-s
144*> U(k) = ( 0 I 0 ) s
145*> ( 0 0 I ) n-k
146*> k-s s n-k
147*>
148*> If s = 1, D(k) overwrites A(k,k), and v overwrites A(1:k-1,k).
149*> If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),
150*> and A(k,k), and v overwrites A(1:k-2,k-1:k).
151*>
152*> If UPLO = 'L', then A = L*D*L**T, where
153*> L = P(1)*L(1)* ... *P(k)*L(k)* ...,
154*> i.e., L is a product of terms P(k)*L(k), where k increases from 1 to
155*> n in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
156*> and 2-by-2 diagonal blocks D(k). P(k) is a permutation matrix as
157*> defined by IPIV(k), and L(k) is a unit lower triangular matrix, such
158*> that if the diagonal block D(k) is of order s (s = 1 or 2), then
159*>
160*> ( I 0 0 ) k-1
161*> L(k) = ( 0 I 0 ) s
162*> ( 0 v I ) n-k-s+1
163*> k-1 s n-k-s+1
164*>
165*> If s = 1, D(k) overwrites A(k,k), and v overwrites A(k+1:n,k).
166*> If s = 2, the lower triangle of D(k) overwrites A(k,k), A(k+1,k),
167*> and A(k+1,k+1), and v overwrites A(k+2:n,k:k+1).
168*> \endverbatim
169*
170*> \par Contributors:
171* ==================
172*>
173*> \verbatim
174*>
175*> 09-29-06 - patch from
176*> Bobby Cheng, MathWorks
177*>
178*> Replace l.209 and l.377
179*> IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
180*> by
181*> IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) .OR. SISNAN(ABSAKK) ) THEN
182*>
183*> 1-96 - Based on modifications by J. Lewis, Boeing Computer Services
184*> Company
185*> \endverbatim
186*
187* =====================================================================
188 SUBROUTINE csytf2( UPLO, N, A, LDA, IPIV, INFO )
189*
190* -- LAPACK computational routine --
191* -- LAPACK is a software package provided by Univ. of Tennessee, --
192* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
193*
194* .. Scalar Arguments ..
195 CHARACTER UPLO
196 INTEGER INFO, LDA, N
197* ..
198* .. Array Arguments ..
199 INTEGER IPIV( * )
200 COMPLEX A( LDA, * )
201* ..
202*
203* =====================================================================
204*
205* .. Parameters ..
206 REAL ZERO, ONE
207 parameter( zero = 0.0e+0, one = 1.0e+0 )
208 REAL EIGHT, SEVTEN
209 parameter( eight = 8.0e+0, sevten = 17.0e+0 )
210 COMPLEX CONE
211 parameter( cone = ( 1.0e+0, 0.0e+0 ) )
212* ..
213* .. Local Scalars ..
214 LOGICAL UPPER
215 INTEGER I, IMAX, J, JMAX, K, KK, KP, KSTEP
216 REAL ABSAKK, ALPHA, COLMAX, ROWMAX
217 COMPLEX D11, D12, D21, D22, R1, T, WK, WKM1, WKP1, Z
218* ..
219* .. External Functions ..
220 LOGICAL LSAME, SISNAN
221 INTEGER ICAMAX
222 EXTERNAL lsame, icamax, sisnan
223* ..
224* .. External Subroutines ..
225 EXTERNAL cscal, cswap, csyr, xerbla
226* ..
227* .. Intrinsic Functions ..
228 INTRINSIC abs, aimag, max, real, sqrt
229* ..
230* .. Statement Functions ..
231 REAL CABS1
232* ..
233* .. Statement Function definitions ..
234 cabs1( z ) = abs( real( z ) ) + abs( aimag( z ) )
235* ..
236* .. Executable Statements ..
237*
238* Test the input parameters.
239*
240 info = 0
241 upper = lsame( uplo, 'U' )
242 IF( .NOT.upper .AND. .NOT.lsame( uplo, 'L' ) ) THEN
243 info = -1
244 ELSE IF( n.LT.0 ) THEN
245 info = -2
246 ELSE IF( lda.LT.max( 1, n ) ) THEN
247 info = -4
248 END IF
249 IF( info.NE.0 ) THEN
250 CALL xerbla( 'CSYTF2', -info )
251 RETURN
252 END IF
253*
254* Initialize ALPHA for use in choosing pivot block size.
255*
256 alpha = ( one+sqrt( sevten ) ) / eight
257*
258 IF( upper ) THEN
259*
260* Factorize A as U*D*U**T using the upper triangle of A
261*
262* K is the main loop index, decreasing from N to 1 in steps of
263* 1 or 2
264*
265 k = n
266 10 CONTINUE
267*
268* If K < 1, exit from loop
269*
270 IF( k.LT.1 )
271 $ GO TO 70
272 kstep = 1
273*
274* Determine rows and columns to be interchanged and whether
275* a 1-by-1 or 2-by-2 pivot block will be used
276*
277 absakk = cabs1( a( k, k ) )
278*
279* IMAX is the row-index of the largest off-diagonal element in
280* column K, and COLMAX is its absolute value.
281* Determine both COLMAX and IMAX.
282*
283 IF( k.GT.1 ) THEN
284 imax = icamax( k-1, a( 1, k ), 1 )
285 colmax = cabs1( a( imax, k ) )
286 ELSE
287 colmax = zero
288 END IF
289*
290 IF( max( absakk, colmax ).EQ.zero .OR. sisnan(absakk) ) THEN
291*
292* Column K is zero or underflow, or contains a NaN:
293* set INFO and continue
294*
295 IF( info.EQ.0 )
296 $ info = k
297 kp = k
298 ELSE
299 IF( absakk.GE.alpha*colmax ) THEN
300*
301* no interchange, use 1-by-1 pivot block
302*
303 kp = k
304 ELSE
305*
306* JMAX is the column-index of the largest off-diagonal
307* element in row IMAX, and ROWMAX is its absolute value
308*
309 jmax = imax + icamax( k-imax, a( imax, imax+1 ), lda )
310 rowmax = cabs1( a( imax, jmax ) )
311 IF( imax.GT.1 ) THEN
312 jmax = icamax( imax-1, a( 1, imax ), 1 )
313 rowmax = max( rowmax, cabs1( a( jmax, imax ) ) )
314 END IF
315*
316 IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
317*
318* no interchange, use 1-by-1 pivot block
319*
320 kp = k
321 ELSE IF( cabs1( a( imax, imax ) ).GE.alpha*rowmax ) THEN
322*
323* interchange rows and columns K and IMAX, use 1-by-1
324* pivot block
325*
326 kp = imax
327 ELSE
328*
329* interchange rows and columns K-1 and IMAX, use 2-by-2
330* pivot block
331*
332 kp = imax
333 kstep = 2
334 END IF
335 END IF
336*
337 kk = k - kstep + 1
338 IF( kp.NE.kk ) THEN
339*
340* Interchange rows and columns KK and KP in the leading
341* submatrix A(1:k,1:k)
342*
343 CALL cswap( kp-1, a( 1, kk ), 1, a( 1, kp ), 1 )
344 CALL cswap( kk-kp-1, a( kp+1, kk ), 1, a( kp, kp+1 ),
345 $ lda )
346 t = a( kk, kk )
347 a( kk, kk ) = a( kp, kp )
348 a( kp, kp ) = t
349 IF( kstep.EQ.2 ) THEN
350 t = a( k-1, k )
351 a( k-1, k ) = a( kp, k )
352 a( kp, k ) = t
353 END IF
354 END IF
355*
356* Update the leading submatrix
357*
358 IF( kstep.EQ.1 ) THEN
359*
360* 1-by-1 pivot block D(k): column k now holds
361*
362* W(k) = U(k)*D(k)
363*
364* where U(k) is the k-th column of U
365*
366* Perform a rank-1 update of A(1:k-1,1:k-1) as
367*
368* A := A - U(k)*D(k)*U(k)**T = A - W(k)*1/D(k)*W(k)**T
369*
370 r1 = cone / a( k, k )
371 CALL csyr( uplo, k-1, -r1, a( 1, k ), 1, a, lda )
372*
373* Store U(k) in column k
374*
375 CALL cscal( k-1, r1, a( 1, k ), 1 )
376 ELSE
377*
378* 2-by-2 pivot block D(k): columns k and k-1 now hold
379*
380* ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
381*
382* where U(k) and U(k-1) are the k-th and (k-1)-th columns
383* of U
384*
385* Perform a rank-2 update of A(1:k-2,1:k-2) as
386*
387* A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**T
388* = A - ( W(k-1) W(k) )*inv(D(k))*( W(k-1) W(k) )**T
389*
390 IF( k.GT.2 ) THEN
391*
392 d12 = a( k-1, k )
393 d22 = a( k-1, k-1 ) / d12
394 d11 = a( k, k ) / d12
395 t = cone / ( d11*d22-cone )
396 d12 = t / d12
397*
398 DO 30 j = k - 2, 1, -1
399 wkm1 = d12*( d11*a( j, k-1 )-a( j, k ) )
400 wk = d12*( d22*a( j, k )-a( j, k-1 ) )
401 DO 20 i = j, 1, -1
402 a( i, j ) = a( i, j ) - a( i, k )*wk -
403 $ a( i, k-1 )*wkm1
404 20 CONTINUE
405 a( j, k ) = wk
406 a( j, k-1 ) = wkm1
407 30 CONTINUE
408*
409 END IF
410*
411 END IF
412 END IF
413*
414* Store details of the interchanges in IPIV
415*
416 IF( kstep.EQ.1 ) THEN
417 ipiv( k ) = kp
418 ELSE
419 ipiv( k ) = -kp
420 ipiv( k-1 ) = -kp
421 END IF
422*
423* Decrease K and return to the start of the main loop
424*
425 k = k - kstep
426 GO TO 10
427*
428 ELSE
429*
430* Factorize A as L*D*L**T using the lower triangle of A
431*
432* K is the main loop index, increasing from 1 to N in steps of
433* 1 or 2
434*
435 k = 1
436 40 CONTINUE
437*
438* If K > N, exit from loop
439*
440 IF( k.GT.n )
441 $ GO TO 70
442 kstep = 1
443*
444* Determine rows and columns to be interchanged and whether
445* a 1-by-1 or 2-by-2 pivot block will be used
446*
447 absakk = cabs1( a( k, k ) )
448*
449* IMAX is the row-index of the largest off-diagonal element in
450* column K, and COLMAX is its absolute value.
451* Determine both COLMAX and IMAX.
452*
453 IF( k.LT.n ) THEN
454 imax = k + icamax( n-k, a( k+1, k ), 1 )
455 colmax = cabs1( a( imax, k ) )
456 ELSE
457 colmax = zero
458 END IF
459*
460 IF( max( absakk, colmax ).EQ.zero .OR. sisnan(absakk) ) THEN
461*
462* Column K is zero or underflow, or contains a NaN:
463* set INFO and continue
464*
465 IF( info.EQ.0 )
466 $ info = k
467 kp = k
468 ELSE
469 IF( absakk.GE.alpha*colmax ) THEN
470*
471* no interchange, use 1-by-1 pivot block
472*
473 kp = k
474 ELSE
475*
476* JMAX is the column-index of the largest off-diagonal
477* element in row IMAX, and ROWMAX is its absolute value
478*
479 jmax = k - 1 + icamax( imax-k, a( imax, k ), lda )
480 rowmax = cabs1( a( imax, jmax ) )
481 IF( imax.LT.n ) THEN
482 jmax = imax + icamax( n-imax, a( imax+1, imax ),
483 $ 1 )
484 rowmax = max( rowmax, cabs1( a( jmax, imax ) ) )
485 END IF
486*
487 IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
488*
489* no interchange, use 1-by-1 pivot block
490*
491 kp = k
492 ELSE IF( cabs1( a( imax, imax ) ).GE.alpha*rowmax ) THEN
493*
494* interchange rows and columns K and IMAX, use 1-by-1
495* pivot block
496*
497 kp = imax
498 ELSE
499*
500* interchange rows and columns K+1 and IMAX, use 2-by-2
501* pivot block
502*
503 kp = imax
504 kstep = 2
505 END IF
506 END IF
507*
508 kk = k + kstep - 1
509 IF( kp.NE.kk ) THEN
510*
511* Interchange rows and columns KK and KP in the trailing
512* submatrix A(k:n,k:n)
513*
514 IF( kp.LT.n )
515 $ CALL cswap( n-kp, a( kp+1, kk ), 1, a( kp+1, kp ),
516 $ 1 )
517 CALL cswap( kp-kk-1, a( kk+1, kk ), 1, a( kp, kk+1 ),
518 $ lda )
519 t = a( kk, kk )
520 a( kk, kk ) = a( kp, kp )
521 a( kp, kp ) = t
522 IF( kstep.EQ.2 ) THEN
523 t = a( k+1, k )
524 a( k+1, k ) = a( kp, k )
525 a( kp, k ) = t
526 END IF
527 END IF
528*
529* Update the trailing submatrix
530*
531 IF( kstep.EQ.1 ) THEN
532*
533* 1-by-1 pivot block D(k): column k now holds
534*
535* W(k) = L(k)*D(k)
536*
537* where L(k) is the k-th column of L
538*
539 IF( k.LT.n ) THEN
540*
541* Perform a rank-1 update of A(k+1:n,k+1:n) as
542*
543* A := A - L(k)*D(k)*L(k)**T = A - W(k)*(1/D(k))*W(k)**T
544*
545 r1 = cone / a( k, k )
546 CALL csyr( uplo, n-k, -r1, a( k+1, k ), 1,
547 $ a( k+1, k+1 ), lda )
548*
549* Store L(k) in column K
550*
551 CALL cscal( n-k, r1, a( k+1, k ), 1 )
552 END IF
553 ELSE
554*
555* 2-by-2 pivot block D(k)
556*
557 IF( k.LT.n-1 ) THEN
558*
559* Perform a rank-2 update of A(k+2:n,k+2:n) as
560*
561* A := A - ( L(k) L(k+1) )*D(k)*( L(k) L(k+1) )**T
562* = A - ( W(k) W(k+1) )*inv(D(k))*( W(k) W(k+1) )**T
563*
564* where L(k) and L(k+1) are the k-th and (k+1)-th
565* columns of L
566*
567 d21 = a( k+1, k )
568 d11 = a( k+1, k+1 ) / d21
569 d22 = a( k, k ) / d21
570 t = cone / ( d11*d22-cone )
571 d21 = t / d21
572*
573 DO 60 j = k + 2, n
574 wk = d21*( d11*a( j, k )-a( j, k+1 ) )
575 wkp1 = d21*( d22*a( j, k+1 )-a( j, k ) )
576 DO 50 i = j, n
577 a( i, j ) = a( i, j ) - a( i, k )*wk -
578 $ a( i, k+1 )*wkp1
579 50 CONTINUE
580 a( j, k ) = wk
581 a( j, k+1 ) = wkp1
582 60 CONTINUE
583 END IF
584 END IF
585 END IF
586*
587* Store details of the interchanges in IPIV
588*
589 IF( kstep.EQ.1 ) THEN
590 ipiv( k ) = kp
591 ELSE
592 ipiv( k ) = -kp
593 ipiv( k+1 ) = -kp
594 END IF
595*
596* Increase K and return to the start of the main loop
597*
598 k = k + kstep
599 GO TO 40
600*
601 END IF
602*
603 70 CONTINUE
604 RETURN
605*
606* End of CSYTF2
607*
608 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine csyr(uplo, n, alpha, x, incx, a, lda)
CSYR performs the symmetric rank-1 update of a complex symmetric matrix.
Definition csyr.f:133
subroutine csytf2(uplo, n, a, lda, ipiv, info)
CSYTF2 computes the factorization of a real symmetric indefinite matrix, using the diagonal pivoting ...
Definition csytf2.f:189
subroutine cscal(n, ca, cx, incx)
CSCAL
Definition cscal.f:78
subroutine cswap(n, cx, incx, cy, incy)
CSWAP
Definition cswap.f:81