6f7fa32146ddfa4a8e2b950bf2ccce9a2c031c20
[platform/upstream/lapack.git] / SRC / chetf2.f
1 *> \brief \b CHETF2 computes the factorization of a complex Hermitian matrix, using the diagonal pivoting method (unblocked algorithm calling Level 2 BLAS).
2 *
3 *  =========== DOCUMENTATION ===========
4 *
5 * Online html documentation available at 
6 *            http://www.netlib.org/lapack/explore-html/ 
7 *
8 *> \htmlonly
9 *> Download CHETF2 + dependencies 
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/chetf2.f"> 
11 *> [TGZ]</a> 
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/chetf2.f"> 
13 *> [ZIP]</a> 
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/chetf2.f"> 
15 *> [TXT]</a>
16 *> \endhtmlonly 
17 *
18 *  Definition:
19 *  ===========
20 *
21 *       SUBROUTINE CHETF2( UPLO, N, A, LDA, IPIV, INFO )
22
23 *       .. Scalar Arguments ..
24 *       CHARACTER          UPLO
25 *       INTEGER            INFO, LDA, N
26 *       ..
27 *       .. Array Arguments ..
28 *       INTEGER            IPIV( * )
29 *       COMPLEX            A( LDA, * )
30 *       ..
31 *  
32 *
33 *> \par Purpose:
34 *  =============
35 *>
36 *> \verbatim
37 *>
38 *> CHETF2 computes the factorization of a complex Hermitian matrix A
39 *> using the Bunch-Kaufman diagonal pivoting method:
40 *>
41 *>    A = U*D*U**H  or  A = L*D*L**H
42 *>
43 *> where U (or L) is a product of permutation and unit upper (lower)
44 *> triangular matrices, U**H is the conjugate transpose of U, and D is
45 *> Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks.
46 *>
47 *> This is the unblocked version of the algorithm, calling Level 2 BLAS.
48 *> \endverbatim
49 *
50 *  Arguments:
51 *  ==========
52 *
53 *> \param[in] UPLO
54 *> \verbatim
55 *>          UPLO is CHARACTER*1
56 *>          Specifies whether the upper or lower triangular part of the
57 *>          Hermitian matrix A is stored:
58 *>          = 'U':  Upper triangular
59 *>          = 'L':  Lower triangular
60 *> \endverbatim
61 *>
62 *> \param[in] N
63 *> \verbatim
64 *>          N is INTEGER
65 *>          The order of the matrix A.  N >= 0.
66 *> \endverbatim
67 *>
68 *> \param[in,out] A
69 *> \verbatim
70 *>          A is COMPLEX array, dimension (LDA,N)
71 *>          On entry, the Hermitian matrix A.  If UPLO = 'U', the leading
72 *>          n-by-n upper triangular part of A contains the upper
73 *>          triangular part of the matrix A, and the strictly lower
74 *>          triangular part of A is not referenced.  If UPLO = 'L', the
75 *>          leading n-by-n lower triangular part of A contains the lower
76 *>          triangular part of the matrix A, and the strictly upper
77 *>          triangular part of A is not referenced.
78 *>
79 *>          On exit, the block diagonal matrix D and the multipliers used
80 *>          to obtain the factor U or L (see below for further details).
81 *> \endverbatim
82 *>
83 *> \param[in] LDA
84 *> \verbatim
85 *>          LDA is INTEGER
86 *>          The leading dimension of the array A.  LDA >= max(1,N).
87 *> \endverbatim
88 *>
89 *> \param[out] IPIV
90 *> \verbatim
91 *>          IPIV is INTEGER array, dimension (N)
92 *>          Details of the interchanges and the block structure of D.
93 *>
94 *>          If UPLO = 'U':
95 *>             If IPIV(k) > 0, then rows and columns k and IPIV(k) were
96 *>             interchanged and D(k,k) is a 1-by-1 diagonal block.
97 *>
98 *>             If IPIV(k) = IPIV(k-1) < 0, then rows and columns
99 *>             k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k)
100 *>             is a 2-by-2 diagonal block.
101 *>
102 *>          If UPLO = 'L':
103 *>             If IPIV(k) > 0, then rows and columns k and IPIV(k) were
104 *>             interchanged and D(k,k) is a 1-by-1 diagonal block.
105 *>
106 *>             If IPIV(k) = IPIV(k+1) < 0, then rows and columns
107 *>             k+1 and -IPIV(k) were interchanged and D(k:k+1,k:k+1)
108 *>             is a 2-by-2 diagonal block.
109 *> \endverbatim
110 *>
111 *> \param[out] INFO
112 *> \verbatim
113 *>          INFO is INTEGER
114 *>          = 0: successful exit
115 *>          < 0: if INFO = -k, the k-th argument had an illegal value
116 *>          > 0: if INFO = k, D(k,k) is exactly zero.  The factorization
117 *>               has been completed, but the block diagonal matrix D is
118 *>               exactly singular, and division by zero will occur if it
119 *>               is used to solve a system of equations.
120 *> \endverbatim
121 *
122 *  Authors:
123 *  ========
124 *
125 *> \author Univ. of Tennessee 
126 *> \author Univ. of California Berkeley 
127 *> \author Univ. of Colorado Denver 
128 *> \author NAG Ltd. 
129 *
130 *> \date November 2013
131 *
132 *> \ingroup complexHEcomputational
133 *
134 *> \par Further Details:
135 *  =====================
136 *>
137 *> \verbatim
138 *>
139 *>  09-29-06 - patch from
140 *>    Bobby Cheng, MathWorks
141 *>
142 *>    Replace l.210 and l.392
143 *>         IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
144 *>    by
145 *>         IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) .OR. SISNAN(ABSAKK) ) THEN
146 *>
147 *>  01-01-96 - Based on modifications by
148 *>    J. Lewis, Boeing Computer Services Company
149 *>    A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA
150 *>
151 *>  If UPLO = 'U', then A = U*D*U**H, where
152 *>     U = P(n)*U(n)* ... *P(k)U(k)* ...,
153 *>  i.e., U is a product of terms P(k)*U(k), where k decreases from n to
154 *>  1 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
155 *>  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as
156 *>  defined by IPIV(k), and U(k) is a unit upper triangular matrix, such
157 *>  that if the diagonal block D(k) is of order s (s = 1 or 2), then
158 *>
159 *>             (   I    v    0   )   k-s
160 *>     U(k) =  (   0    I    0   )   s
161 *>             (   0    0    I   )   n-k
162 *>                k-s   s   n-k
163 *>
164 *>  If s = 1, D(k) overwrites A(k,k), and v overwrites A(1:k-1,k).
165 *>  If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),
166 *>  and A(k,k), and v overwrites A(1:k-2,k-1:k).
167 *>
168 *>  If UPLO = 'L', then A = L*D*L**H, where
169 *>     L = P(1)*L(1)* ... *P(k)*L(k)* ...,
170 *>  i.e., L is a product of terms P(k)*L(k), where k increases from 1 to
171 *>  n in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
172 *>  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as
173 *>  defined by IPIV(k), and L(k) is a unit lower triangular matrix, such
174 *>  that if the diagonal block D(k) is of order s (s = 1 or 2), then
175 *>
176 *>             (   I    0     0   )  k-1
177 *>     L(k) =  (   0    I     0   )  s
178 *>             (   0    v     I   )  n-k-s+1
179 *>                k-1   s  n-k-s+1
180 *>
181 *>  If s = 1, D(k) overwrites A(k,k), and v overwrites A(k+1:n,k).
182 *>  If s = 2, the lower triangle of D(k) overwrites A(k,k), A(k+1,k),
183 *>  and A(k+1,k+1), and v overwrites A(k+2:n,k:k+1).
184 *> \endverbatim
185 *>
186 *  =====================================================================
187       SUBROUTINE CHETF2( UPLO, N, A, LDA, IPIV, INFO )
188 *
189 *  -- LAPACK computational routine (version 3.5.0) --
190 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
191 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
192 *     November 2013
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 *     ..
211 *     .. Local Scalars ..
212       LOGICAL            UPPER
213       INTEGER            I, IMAX, J, JMAX, K, KK, KP, KSTEP
214       REAL               ABSAKK, ALPHA, COLMAX, D, D11, D22, R1, ROWMAX,
215      $                   TT
216       COMPLEX            D12, D21, T, WK, WKM1, WKP1, ZDUM
217 *     ..
218 *     .. External Functions ..
219       LOGICAL            LSAME, SISNAN
220       INTEGER            ICAMAX
221       REAL               SLAPY2
222       EXTERNAL           LSAME, ICAMAX, SLAPY2, SISNAN
223 *     ..
224 *     .. External Subroutines ..
225       EXTERNAL           CHER, CSSCAL, CSWAP, XERBLA
226 *     ..
227 *     .. Intrinsic Functions ..
228       INTRINSIC          ABS, AIMAG, CMPLX, CONJG, MAX, REAL, SQRT
229 *     ..
230 *     .. Statement Functions ..
231       REAL               CABS1
232 *     ..
233 *     .. Statement Function definitions ..
234       CABS1( ZDUM ) = ABS( REAL( ZDUM ) ) + ABS( AIMAG( ZDUM ) )
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( 'CHETF2', -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**H 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 90
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 = ABS( REAL( 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 or underflow, or contains a NaN:
293 *           set INFO and continue
294 *
295             IF( INFO.EQ.0 )
296      $         INFO = K
297             KP = K
298             A( K, K ) = REAL( A( K, K ) )
299          ELSE
300             IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
301 *
302 *              no interchange, use 1-by-1 pivot block
303 *
304                KP = K
305             ELSE
306 *
307 *              JMAX is the column-index of the largest off-diagonal
308 *              element in row IMAX, and ROWMAX is its absolute value
309 *
310                JMAX = IMAX + ICAMAX( K-IMAX, A( IMAX, IMAX+1 ), LDA )
311                ROWMAX = CABS1( A( IMAX, JMAX ) )
312                IF( IMAX.GT.1 ) THEN
313                   JMAX = ICAMAX( IMAX-1, A( 1, IMAX ), 1 )
314                   ROWMAX = MAX( ROWMAX, CABS1( A( JMAX, IMAX ) ) )
315                END IF
316 *
317                IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
318 *
319 *                 no interchange, use 1-by-1 pivot block
320 *
321                   KP = K
322                ELSE IF( ABS( REAL( A( IMAX, IMAX ) ) ).GE.ALPHA*ROWMAX )
323      $                   THEN
324 *
325 *                 interchange rows and columns K and IMAX, use 1-by-1
326 *                 pivot block
327 *
328                   KP = IMAX
329                ELSE
330 *
331 *                 interchange rows and columns K-1 and IMAX, use 2-by-2
332 *                 pivot block
333 *
334                   KP = IMAX
335                   KSTEP = 2
336                END IF
337             END IF
338 *
339             KK = K - KSTEP + 1
340             IF( KP.NE.KK ) THEN
341 *
342 *              Interchange rows and columns KK and KP in the leading
343 *              submatrix A(1:k,1:k)
344 *
345                CALL CSWAP( KP-1, A( 1, KK ), 1, A( 1, KP ), 1 )
346                DO 20 J = KP + 1, KK - 1
347                   T = CONJG( A( J, KK ) )
348                   A( J, KK ) = CONJG( A( KP, J ) )
349                   A( KP, J ) = T
350    20          CONTINUE
351                A( KP, KK ) = CONJG( A( KP, KK ) )
352                R1 = REAL( A( KK, KK ) )
353                A( KK, KK ) = REAL( A( KP, KP ) )
354                A( KP, KP ) = R1
355                IF( KSTEP.EQ.2 ) THEN
356                   A( K, K ) = REAL( A( K, K ) )
357                   T = A( K-1, K )
358                   A( K-1, K ) = A( KP, K )
359                   A( KP, K ) = T
360                END IF
361             ELSE
362                A( K, K ) = REAL( A( K, K ) )
363                IF( KSTEP.EQ.2 )
364      $            A( K-1, K-1 ) = REAL( A( K-1, K-1 ) )
365             END IF
366 *
367 *           Update the leading submatrix
368 *
369             IF( KSTEP.EQ.1 ) THEN
370 *
371 *              1-by-1 pivot block D(k): column k now holds
372 *
373 *              W(k) = U(k)*D(k)
374 *
375 *              where U(k) is the k-th column of U
376 *
377 *              Perform a rank-1 update of A(1:k-1,1:k-1) as
378 *
379 *              A := A - U(k)*D(k)*U(k)**H = A - W(k)*1/D(k)*W(k)**H
380 *
381                R1 = ONE / REAL( A( K, K ) )
382                CALL CHER( UPLO, K-1, -R1, A( 1, K ), 1, A, LDA )
383 *
384 *              Store U(k) in column k
385 *
386                CALL CSSCAL( K-1, R1, A( 1, K ), 1 )
387             ELSE
388 *
389 *              2-by-2 pivot block D(k): columns k and k-1 now hold
390 *
391 *              ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
392 *
393 *              where U(k) and U(k-1) are the k-th and (k-1)-th columns
394 *              of U
395 *
396 *              Perform a rank-2 update of A(1:k-2,1:k-2) as
397 *
398 *              A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**H
399 *                 = A - ( W(k-1) W(k) )*inv(D(k))*( W(k-1) W(k) )**H
400 *
401                IF( K.GT.2 ) THEN
402 *
403                   D = SLAPY2( REAL( A( K-1, K ) ),
404      $                AIMAG( A( K-1, K ) ) )
405                   D22 = REAL( A( K-1, K-1 ) ) / D
406                   D11 = REAL( A( K, K ) ) / D
407                   TT = ONE / ( D11*D22-ONE )
408                   D12 = A( K-1, K ) / D
409                   D = TT / D
410 *
411                   DO 40 J = K - 2, 1, -1
412                      WKM1 = D*( D11*A( J, K-1 )-CONJG( D12 )*A( J, K ) )
413                      WK = D*( D22*A( J, K )-D12*A( J, K-1 ) )
414                      DO 30 I = J, 1, -1
415                         A( I, J ) = A( I, J ) - A( I, K )*CONJG( WK ) -
416      $                              A( I, K-1 )*CONJG( WKM1 )
417    30                CONTINUE
418                      A( J, K ) = WK
419                      A( J, K-1 ) = WKM1
420                      A( J, J ) = CMPLX( REAL( A( J, J ) ), 0.0E+0 )
421    40             CONTINUE
422 *
423                END IF
424 *
425             END IF
426          END IF
427 *
428 *        Store details of the interchanges in IPIV
429 *
430          IF( KSTEP.EQ.1 ) THEN
431             IPIV( K ) = KP
432          ELSE
433             IPIV( K ) = -KP
434             IPIV( K-1 ) = -KP
435          END IF
436 *
437 *        Decrease K and return to the start of the main loop
438 *
439          K = K - KSTEP
440          GO TO 10
441 *
442       ELSE
443 *
444 *        Factorize A as L*D*L**H using the lower triangle of A
445 *
446 *        K is the main loop index, increasing from 1 to N in steps of
447 *        1 or 2
448 *
449          K = 1
450    50    CONTINUE
451 *
452 *        If K > N, exit from loop
453 *
454          IF( K.GT.N )
455      $      GO TO 90
456          KSTEP = 1
457 *
458 *        Determine rows and columns to be interchanged and whether
459 *        a 1-by-1 or 2-by-2 pivot block will be used
460 *
461          ABSAKK = ABS( REAL( A( K, K ) ) )
462 *
463 *        IMAX is the row-index of the largest off-diagonal element in
464 *        column K, and COLMAX is its absolute value.
465 *        Determine both COLMAX and IMAX.
466 *
467          IF( K.LT.N ) THEN
468             IMAX = K + ICAMAX( N-K, A( K+1, K ), 1 )
469             COLMAX = CABS1( A( IMAX, K ) )
470          ELSE
471             COLMAX = ZERO
472          END IF
473 *
474          IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) .OR. SISNAN(ABSAKK) ) THEN
475 *
476 *           Column K is zero or underflow, contains a NaN:
477 *           set INFO and continue
478 *
479             IF( INFO.EQ.0 )
480      $         INFO = K
481             KP = K
482             A( K, K ) = REAL( A( K, K ) )
483          ELSE
484             IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
485 *
486 *              no interchange, use 1-by-1 pivot block
487 *
488                KP = K
489             ELSE
490 *
491 *              JMAX is the column-index of the largest off-diagonal
492 *              element in row IMAX, and ROWMAX is its absolute value
493 *
494                JMAX = K - 1 + ICAMAX( IMAX-K, A( IMAX, K ), LDA )
495                ROWMAX = CABS1( A( IMAX, JMAX ) )
496                IF( IMAX.LT.N ) THEN
497                   JMAX = IMAX + ICAMAX( N-IMAX, A( IMAX+1, IMAX ), 1 )
498                   ROWMAX = MAX( ROWMAX, CABS1( A( JMAX, IMAX ) ) )
499                END IF
500 *
501                IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
502 *
503 *                 no interchange, use 1-by-1 pivot block
504 *
505                   KP = K
506                ELSE IF( ABS( REAL( A( IMAX, IMAX ) ) ).GE.ALPHA*ROWMAX )
507      $                   THEN
508 *
509 *                 interchange rows and columns K and IMAX, use 1-by-1
510 *                 pivot block
511 *
512                   KP = IMAX
513                ELSE
514 *
515 *                 interchange rows and columns K+1 and IMAX, use 2-by-2
516 *                 pivot block
517 *
518                   KP = IMAX
519                   KSTEP = 2
520                END IF
521             END IF
522 *
523             KK = K + KSTEP - 1
524             IF( KP.NE.KK ) THEN
525 *
526 *              Interchange rows and columns KK and KP in the trailing
527 *              submatrix A(k:n,k:n)
528 *
529                IF( KP.LT.N )
530      $            CALL CSWAP( N-KP, A( KP+1, KK ), 1, A( KP+1, KP ), 1 )
531                DO 60 J = KK + 1, KP - 1
532                   T = CONJG( A( J, KK ) )
533                   A( J, KK ) = CONJG( A( KP, J ) )
534                   A( KP, J ) = T
535    60          CONTINUE
536                A( KP, KK ) = CONJG( A( KP, KK ) )
537                R1 = REAL( A( KK, KK ) )
538                A( KK, KK ) = REAL( A( KP, KP ) )
539                A( KP, KP ) = R1
540                IF( KSTEP.EQ.2 ) THEN
541                   A( K, K ) = REAL( A( K, K ) )
542                   T = A( K+1, K )
543                   A( K+1, K ) = A( KP, K )
544                   A( KP, K ) = T
545                END IF
546             ELSE
547                A( K, K ) = REAL( A( K, K ) )
548                IF( KSTEP.EQ.2 )
549      $            A( K+1, K+1 ) = REAL( A( K+1, K+1 ) )
550             END IF
551 *
552 *           Update the trailing submatrix
553 *
554             IF( KSTEP.EQ.1 ) THEN
555 *
556 *              1-by-1 pivot block D(k): column k now holds
557 *
558 *              W(k) = L(k)*D(k)
559 *
560 *              where L(k) is the k-th column of L
561 *
562                IF( K.LT.N ) THEN
563 *
564 *                 Perform a rank-1 update of A(k+1:n,k+1:n) as
565 *
566 *                 A := A - L(k)*D(k)*L(k)**H = A - W(k)*(1/D(k))*W(k)**H
567 *
568                   R1 = ONE / REAL( A( K, K ) )
569                   CALL CHER( UPLO, N-K, -R1, A( K+1, K ), 1,
570      $                       A( K+1, K+1 ), LDA )
571 *
572 *                 Store L(k) in column K
573 *
574                   CALL CSSCAL( N-K, R1, A( K+1, K ), 1 )
575                END IF
576             ELSE
577 *
578 *              2-by-2 pivot block D(k)
579 *
580                IF( K.LT.N-1 ) THEN
581 *
582 *                 Perform a rank-2 update of A(k+2:n,k+2:n) as
583 *
584 *                 A := A - ( L(k) L(k+1) )*D(k)*( L(k) L(k+1) )**H
585 *                    = A - ( W(k) W(k+1) )*inv(D(k))*( W(k) W(k+1) )**H
586 *
587 *                 where L(k) and L(k+1) are the k-th and (k+1)-th
588 *                 columns of L
589 *
590                   D = SLAPY2( REAL( A( K+1, K ) ),
591      $                        AIMAG( A( K+1, K ) ) )
592                   D11 = REAL( A( K+1, K+1 ) ) / D
593                   D22 = REAL( A( K, K ) ) / D
594                   TT = ONE / ( D11*D22-ONE )
595                   D21 = A( K+1, K ) / D
596                   D =  TT / D
597 *
598                   DO 80 J = K + 2, N
599                      WK = D*( D11*A( J, K )-D21*A( J, K+1 ) )
600                      WKP1 = D*( D22*A( J, K+1 )-CONJG( D21 )*A( J, K ) )
601                      DO 70 I = J, N
602                         A( I, J ) = A( I, J ) - A( I, K )*CONJG( WK ) -
603      $                              A( I, K+1 )*CONJG( WKP1 )
604    70                CONTINUE
605                      A( J, K ) = WK
606                      A( J, K+1 ) = WKP1
607                      A( J, J ) = CMPLX( REAL( A( J, J ) ), 0.0E+0 )
608    80             CONTINUE
609                END IF
610             END IF
611          END IF
612 *
613 *        Store details of the interchanges in IPIV
614 *
615          IF( KSTEP.EQ.1 ) THEN
616             IPIV( K ) = KP
617          ELSE
618             IPIV( K ) = -KP
619             IPIV( K+1 ) = -KP
620          END IF
621 *
622 *        Increase K and return to the start of the main loop
623 *
624          K = K + KSTEP
625          GO TO 50
626 *
627       END IF
628 *
629    90 CONTINUE
630       RETURN
631 *
632 *     End of CHETF2
633 *
634       END