1       SUBROUTINE ZHETF2( UPLO, N, A, LDA, IPIV, INFO )
  2 *
  3 *  -- LAPACK routine (version 3.3.1) --
  4 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  5 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  6 *  -- April 2011                                                      --
  7 *
  8 *     .. Scalar Arguments ..
  9       CHARACTER          UPLO
 10       INTEGER            INFO, LDA, N
 11 *     ..
 12 *     .. Array Arguments ..
 13       INTEGER            IPIV( * )
 14       COMPLEX*16         A( LDA, * )
 15 *     ..
 16 *
 17 *  Purpose
 18 *  =======
 19 *
 20 *  ZHETF2 computes the factorization of a complex Hermitian matrix A
 21 *  using the Bunch-Kaufman diagonal pivoting method:
 22 *
 23 *     A = U*D*U**H  or  A = L*D*L**H
 24 *
 25 *  where U (or L) is a product of permutation and unit upper (lower)
 26 *  triangular matrices, U**H is the conjugate transpose of U, and D is
 27 *  Hermitian and block diagonal with 1-by-1 and 2-by-2 diagonal blocks.
 28 *
 29 *  This is the unblocked version of the algorithm, calling Level 2 BLAS.
 30 *
 31 *  Arguments
 32 *  =========
 33 *
 34 *  UPLO    (input) CHARACTER*1
 35 *          Specifies whether the upper or lower triangular part of the
 36 *          Hermitian matrix A is stored:
 37 *          = 'U':  Upper triangular
 38 *          = 'L':  Lower triangular
 39 *
 40 *  N       (input) INTEGER
 41 *          The order of the matrix A.  N >= 0.
 42 *
 43 *  A       (input/output) COMPLEX*16 array, dimension (LDA,N)
 44 *          On entry, the Hermitian matrix A.  If UPLO = 'U', the leading
 45 *          n-by-n upper triangular part of A contains the upper
 46 *          triangular part of the matrix A, and the strictly lower
 47 *          triangular part of A is not referenced.  If UPLO = 'L', the
 48 *          leading n-by-n lower triangular part of A contains the lower
 49 *          triangular part of the matrix A, and the strictly upper
 50 *          triangular part of A is not referenced.
 51 *
 52 *          On exit, the block diagonal matrix D and the multipliers used
 53 *          to obtain the factor U or L (see below for further details).
 54 *
 55 *  LDA     (input) INTEGER
 56 *          The leading dimension of the array A.  LDA >= max(1,N).
 57 *
 58 *  IPIV    (output) INTEGER array, dimension (N)
 59 *          Details of the interchanges and the block structure of D.
 60 *          If IPIV(k) > 0, then rows and columns k and IPIV(k) were
 61 *          interchanged and D(k,k) is a 1-by-1 diagonal block.
 62 *          If UPLO = 'U' and IPIV(k) = IPIV(k-1) < 0, then rows and
 63 *          columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k)
 64 *          is a 2-by-2 diagonal block.  If UPLO = 'L' and IPIV(k) =
 65 *          IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were
 66 *          interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block.
 67 *
 68 *  INFO    (output) INTEGER
 69 *          = 0: successful exit
 70 *          < 0: if INFO = -k, the k-th argument had an illegal value
 71 *          > 0: if INFO = k, D(k,k) is exactly zero.  The factorization
 72 *               has been completed, but the block diagonal matrix D is
 73 *               exactly singular, and division by zero will occur if it
 74 *               is used to solve a system of equations.
 75 *
 76 *  Further Details
 77 *  ===============
 78 *
 79 *  09-29-06 - patch from
 80 *    Bobby Cheng, MathWorks
 81 *
 82 *    Replace l.210 and l.393
 83 *         IF( MAX( ABSAKK, COLMAX ).EQ.ZERO ) THEN
 84 *    by
 85 *         IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) .OR. DISNAN(ABSAKK) ) THEN
 86 *
 87 *  01-01-96 - Based on modifications by
 88 *    J. Lewis, Boeing Computer Services Company
 89 *    A. Petitet, Computer Science Dept., Univ. of Tenn., Knoxville, USA
 90 *
 91 *  If UPLO = 'U', then A = U*D*U**H, where
 92 *     U = P(n)*U(n)* ... *P(k)U(k)* ...,
 93 *  i.e., U is a product of terms P(k)*U(k), where k decreases from n to
 94 *  1 in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
 95 *  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as
 96 *  defined by IPIV(k), and U(k) is a unit upper triangular matrix, such
 97 *  that if the diagonal block D(k) is of order s (s = 1 or 2), then
 98 *
 99 *             (   I    v    0   )   k-s
100 *     U(k) =  (   0    I    0   )   s
101 *             (   0    0    I   )   n-k
102 *                k-s   s   n-k
103 *
104 *  If s = 1, D(k) overwrites A(k,k), and v overwrites A(1:k-1,k).
105 *  If s = 2, the upper triangle of D(k) overwrites A(k-1,k-1), A(k-1,k),
106 *  and A(k,k), and v overwrites A(1:k-2,k-1:k).
107 *
108 *  If UPLO = 'L', then A = L*D*L**H, where
109 *     L = P(1)*L(1)* ... *P(k)*L(k)* ...,
110 *  i.e., L is a product of terms P(k)*L(k), where k increases from 1 to
111 *  n in steps of 1 or 2, and D is a block diagonal matrix with 1-by-1
112 *  and 2-by-2 diagonal blocks D(k).  P(k) is a permutation matrix as
113 *  defined by IPIV(k), and L(k) is a unit lower triangular matrix, such
114 *  that if the diagonal block D(k) is of order s (s = 1 or 2), then
115 *
116 *             (   I    0     0   )  k-1
117 *     L(k) =  (   0    I     0   )  s
118 *             (   0    v     I   )  n-k-s+1
119 *                k-1   s  n-k-s+1
120 *
121 *  If s = 1, D(k) overwrites A(k,k), and v overwrites A(k+1:n,k).
122 *  If s = 2, the lower triangle of D(k) overwrites A(k,k), A(k+1,k),
123 *  and A(k+1,k+1), and v overwrites A(k+2:n,k:k+1).
124 *
125 *  =====================================================================
126 *
127 *     .. Parameters ..
128       DOUBLE PRECISION   ZERO, ONE
129       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
130       DOUBLE PRECISION   EIGHT, SEVTEN
131       PARAMETER          ( EIGHT = 8.0D+0, SEVTEN = 17.0D+0 )
132 *     ..
133 *     .. Local Scalars ..
134       LOGICAL            UPPER
135       INTEGER            I, IMAX, J, JMAX, K, KK, KP, KSTEP
136       DOUBLE PRECISION   ABSAKK, ALPHA, COLMAX, D, D11, D22, R1, ROWMAX,
137      $                   TT
138       COMPLEX*16         D12, D21, T, WK, WKM1, WKP1, ZDUM
139 *     ..
140 *     .. External Functions ..
141       LOGICAL            LSAME, DISNAN
142       INTEGER            IZAMAX
143       DOUBLE PRECISION   DLAPY2
144       EXTERNAL           LSAME, IZAMAX, DLAPY2, DISNAN
145 *     ..
146 *     .. External Subroutines ..
147       EXTERNAL           XERBLA, ZDSCAL, ZHER, ZSWAP
148 *     ..
149 *     .. Intrinsic Functions ..
150       INTRINSIC          ABSDBLEDCMPLXDCONJGDIMAGMAXSQRT
151 *     ..
152 *     .. Statement Functions ..
153       DOUBLE PRECISION   CABS1
154 *     ..
155 *     .. Statement Function definitions ..
156       CABS1( ZDUM ) = ABSDBLE( ZDUM ) ) + ABSDIMAG( ZDUM ) )
157 *     ..
158 *     .. Executable Statements ..
159 *
160 *     Test the input parameters.
161 *
162       INFO = 0
163       UPPER = LSAME( UPLO, 'U' )
164       IF.NOT.UPPER .AND. .NOT.LSAME( UPLO, 'L' ) ) THEN
165          INFO = -1
166       ELSE IF( N.LT.0 ) THEN
167          INFO = -2
168       ELSE IF( LDA.LT.MAX1, N ) ) THEN
169          INFO = -4
170       END IF
171       IF( INFO.NE.0 ) THEN
172          CALL XERBLA( 'ZHETF2'-INFO )
173          RETURN
174       END IF
175 *
176 *     Initialize ALPHA for use in choosing pivot block size.
177 *
178       ALPHA = ( ONE+SQRT( SEVTEN ) ) / EIGHT
179 *
180       IF( UPPER ) THEN
181 *
182 *        Factorize A as U*D*U**H using the upper triangle of A
183 *
184 *        K is the main loop index, decreasing from N to 1 in steps of
185 *        1 or 2
186 *
187          K = N
188    10    CONTINUE
189 *
190 *        If K < 1, exit from loop
191 *
192          IF( K.LT.1 )
193      $      GO TO 90
194          KSTEP = 1
195 *
196 *        Determine rows and columns to be interchanged and whether
197 *        a 1-by-1 or 2-by-2 pivot block will be used
198 *
199          ABSAKK = ABSDBLE( A( K, K ) ) )
200 *
201 *        IMAX is the row-index of the largest off-diagonal element in
202 *        column K, and COLMAX is its absolute value
203 *
204          IF( K.GT.1 ) THEN
205             IMAX = IZAMAX( K-1, A( 1, K ), 1 )
206             COLMAX = CABS1( A( IMAX, K ) )
207          ELSE
208             COLMAX = ZERO
209          END IF
210 *
211          IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) .OR. DISNAN(ABSAKK) ) THEN
212 *
213 *           Column K is zero or contains a NaN: set INFO and continue
214 *
215             IF( INFO.EQ.0 )
216      $         INFO = K
217             KP = K
218             A( K, K ) = DBLE( A( K, K ) )
219          ELSE
220             IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
221 *
222 *              no interchange, use 1-by-1 pivot block
223 *
224                KP = K
225             ELSE
226 *
227 *              JMAX is the column-index of the largest off-diagonal
228 *              element in row IMAX, and ROWMAX is its absolute value
229 *
230                JMAX = IMAX + IZAMAX( K-IMAX, A( IMAX, IMAX+1 ), LDA )
231                ROWMAX = CABS1( A( IMAX, JMAX ) )
232                IF( IMAX.GT.1 ) THEN
233                   JMAX = IZAMAX( IMAX-1, A( 1, IMAX ), 1 )
234                   ROWMAX = MAX( ROWMAX, CABS1( A( JMAX, IMAX ) ) )
235                END IF
236 *
237                IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
238 *
239 *                 no interchange, use 1-by-1 pivot block
240 *
241                   KP = K
242                ELSE IFABSDBLE( A( IMAX, IMAX ) ) ).GE.ALPHA*ROWMAX )
243      $                   THEN
244 *
245 *                 interchange rows and columns K and IMAX, use 1-by-1
246 *                 pivot block
247 *
248                   KP = IMAX
249                ELSE
250 *
251 *                 interchange rows and columns K-1 and IMAX, use 2-by-2
252 *                 pivot block
253 *
254                   KP = IMAX
255                   KSTEP = 2
256                END IF
257             END IF
258 *
259             KK = K - KSTEP + 1
260             IF( KP.NE.KK ) THEN
261 *
262 *              Interchange rows and columns KK and KP in the leading
263 *              submatrix A(1:k,1:k)
264 *
265                CALL ZSWAP( KP-1, A( 1, KK ), 1, A( 1, KP ), 1 )
266                DO 20 J = KP + 1, KK - 1
267                   T = DCONJG( A( J, KK ) )
268                   A( J, KK ) = DCONJG( A( KP, J ) )
269                   A( KP, J ) = T
270    20          CONTINUE
271                A( KP, KK ) = DCONJG( A( KP, KK ) )
272                R1 = DBLE( A( KK, KK ) )
273                A( KK, KK ) = DBLE( A( KP, KP ) )
274                A( KP, KP ) = R1
275                IF( KSTEP.EQ.2 ) THEN
276                   A( K, K ) = DBLE( A( K, K ) )
277                   T = A( K-1, K )
278                   A( K-1, K ) = A( KP, K )
279                   A( KP, K ) = T
280                END IF
281             ELSE
282                A( K, K ) = DBLE( A( K, K ) )
283                IF( KSTEP.EQ.2 )
284      $            A( K-1, K-1 ) = DBLE( A( K-1, K-1 ) )
285             END IF
286 *
287 *           Update the leading submatrix
288 *
289             IF( KSTEP.EQ.1 ) THEN
290 *
291 *              1-by-1 pivot block D(k): column k now holds
292 *
293 *              W(k) = U(k)*D(k)
294 *
295 *              where U(k) is the k-th column of U
296 *
297 *              Perform a rank-1 update of A(1:k-1,1:k-1) as
298 *
299 *              A := A - U(k)*D(k)*U(k)**H = A - W(k)*1/D(k)*W(k)**H
300 *
301                R1 = ONE / DBLE( A( K, K ) )
302                CALL ZHER( UPLO, K-1-R1, A( 1, K ), 1, A, LDA )
303 *
304 *              Store U(k) in column k
305 *
306                CALL ZDSCAL( K-1, R1, A( 1, K ), 1 )
307             ELSE
308 *
309 *              2-by-2 pivot block D(k): columns k and k-1 now hold
310 *
311 *              ( W(k-1) W(k) ) = ( U(k-1) U(k) )*D(k)
312 *
313 *              where U(k) and U(k-1) are the k-th and (k-1)-th columns
314 *              of U
315 *
316 *              Perform a rank-2 update of A(1:k-2,1:k-2) as
317 *
318 *              A := A - ( U(k-1) U(k) )*D(k)*( U(k-1) U(k) )**H
319 *                 = A - ( W(k-1) W(k) )*inv(D(k))*( W(k-1) W(k) )**H
320 *
321                IF( K.GT.2 ) THEN
322 *
323                   D = DLAPY2( DBLE( A( K-1, K ) ),
324      $                DIMAG( A( K-1, K ) ) )
325                   D22 = DBLE( A( K-1, K-1 ) ) / D
326                   D11 = DBLE( A( K, K ) ) / D
327                   TT = ONE / ( D11*D22-ONE )
328                   D12 = A( K-1, K ) / D
329                   D = TT / D
330 *
331                   DO 40 J = K - 21-1
332                      WKM1 = D*( D11*A( J, K-1 )-DCONJG( D12 )*
333      $                      A( J, K ) )
334                      WK = D*( D22*A( J, K )-D12*A( J, K-1 ) )
335                      DO 30 I = J, 1-1
336                         A( I, J ) = A( I, J ) - A( I, K )*DCONJG( WK ) -
337      $                              A( I, K-1 )*DCONJG( WKM1 )
338    30                CONTINUE
339                      A( J, K ) = WK
340                      A( J, K-1 ) = WKM1
341                      A( J, J ) = DCMPLXDBLE( A( J, J ) ), 0.0D+0 )
342    40             CONTINUE
343 *
344                END IF
345 *
346             END IF
347          END IF
348 *
349 *        Store details of the interchanges in IPIV
350 *
351          IF( KSTEP.EQ.1 ) THEN
352             IPIV( K ) = KP
353          ELSE
354             IPIV( K ) = -KP
355             IPIV( K-1 ) = -KP
356          END IF
357 *
358 *        Decrease K and return to the start of the main loop
359 *
360          K = K - KSTEP
361          GO TO 10
362 *
363       ELSE
364 *
365 *        Factorize A as L*D*L**H using the lower triangle of A
366 *
367 *        K is the main loop index, increasing from 1 to N in steps of
368 *        1 or 2
369 *
370          K = 1
371    50    CONTINUE
372 *
373 *        If K > N, exit from loop
374 *
375          IF( K.GT.N )
376      $      GO TO 90
377          KSTEP = 1
378 *
379 *        Determine rows and columns to be interchanged and whether
380 *        a 1-by-1 or 2-by-2 pivot block will be used
381 *
382          ABSAKK = ABSDBLE( A( K, K ) ) )
383 *
384 *        IMAX is the row-index of the largest off-diagonal element in
385 *        column K, and COLMAX is its absolute value
386 *
387          IF( K.LT.N ) THEN
388             IMAX = K + IZAMAX( N-K, A( K+1, K ), 1 )
389             COLMAX = CABS1( A( IMAX, K ) )
390          ELSE
391             COLMAX = ZERO
392          END IF
393 *
394          IF( (MAX( ABSAKK, COLMAX ).EQ.ZERO) .OR. DISNAN(ABSAKK) ) THEN
395 *
396 *           Column K is zero or contains a NaN: set INFO and continue
397 *
398             IF( INFO.EQ.0 )
399      $         INFO = K
400             KP = K
401             A( K, K ) = DBLE( A( K, K ) )
402          ELSE
403             IF( ABSAKK.GE.ALPHA*COLMAX ) THEN
404 *
405 *              no interchange, use 1-by-1 pivot block
406 *
407                KP = K
408             ELSE
409 *
410 *              JMAX is the column-index of the largest off-diagonal
411 *              element in row IMAX, and ROWMAX is its absolute value
412 *
413                JMAX = K - 1 + IZAMAX( IMAX-K, A( IMAX, K ), LDA )
414                ROWMAX = CABS1( A( IMAX, JMAX ) )
415                IF( IMAX.LT.N ) THEN
416                   JMAX = IMAX + IZAMAX( N-IMAX, A( IMAX+1, IMAX ), 1 )
417                   ROWMAX = MAX( ROWMAX, CABS1( A( JMAX, IMAX ) ) )
418                END IF
419 *
420                IF( ABSAKK.GE.ALPHA*COLMAX*( COLMAX / ROWMAX ) ) THEN
421 *
422 *                 no interchange, use 1-by-1 pivot block
423 *
424                   KP = K
425                ELSE IFABSDBLE( A( IMAX, IMAX ) ) ).GE.ALPHA*ROWMAX )
426      $                   THEN
427 *
428 *                 interchange rows and columns K and IMAX, use 1-by-1
429 *                 pivot block
430 *
431                   KP = IMAX
432                ELSE
433 *
434 *                 interchange rows and columns K+1 and IMAX, use 2-by-2
435 *                 pivot block
436 *
437                   KP = IMAX
438                   KSTEP = 2
439                END IF
440             END IF
441 *
442             KK = K + KSTEP - 1
443             IF( KP.NE.KK ) THEN
444 *
445 *              Interchange rows and columns KK and KP in the trailing
446 *              submatrix A(k:n,k:n)
447 *
448                IF( KP.LT.N )
449      $            CALL ZSWAP( N-KP, A( KP+1, KK ), 1, A( KP+1, KP ), 1 )
450                DO 60 J = KK + 1, KP - 1
451                   T = DCONJG( A( J, KK ) )
452                   A( J, KK ) = DCONJG( A( KP, J ) )
453                   A( KP, J ) = T
454    60          CONTINUE
455                A( KP, KK ) = DCONJG( A( KP, KK ) )
456                R1 = DBLE( A( KK, KK ) )
457                A( KK, KK ) = DBLE( A( KP, KP ) )
458                A( KP, KP ) = R1
459                IF( KSTEP.EQ.2 ) THEN
460                   A( K, K ) = DBLE( A( K, K ) )
461                   T = A( K+1, K )
462                   A( K+1, K ) = A( KP, K )
463                   A( KP, K ) = T
464                END IF
465             ELSE
466                A( K, K ) = DBLE( A( K, K ) )
467                IF( KSTEP.EQ.2 )
468      $            A( K+1, K+1 ) = DBLE( A( K+1, K+1 ) )
469             END IF
470 *
471 *           Update the trailing submatrix
472 *
473             IF( KSTEP.EQ.1 ) THEN
474 *
475 *              1-by-1 pivot block D(k): column k now holds
476 *
477 *              W(k) = L(k)*D(k)
478 *
479 *              where L(k) is the k-th column of L
480 *
481                IF( K.LT.N ) THEN
482 *
483 *                 Perform a rank-1 update of A(k+1:n,k+1:n) as
484 *
485 *                 A := A - L(k)*D(k)*L(k)**H = A - W(k)*(1/D(k))*W(k)**H
486 *
487                   R1 = ONE / DBLE( A( K, K ) )
488                   CALL ZHER( UPLO, N-K, -R1, A( K+1, K ), 1,
489      $                       A( K+1, K+1 ), LDA )
490 *
491 *                 Store L(k) in column K
492 *
493                   CALL ZDSCAL( N-K, R1, A( K+1, K ), 1 )
494                END IF
495             ELSE
496 *
497 *              2-by-2 pivot block D(k)
498 *
499                IF( K.LT.N-1 ) THEN
500 *
501 *                 Perform a rank-2 update of A(k+2:n,k+2:n) as
502 *
503 *                 A := A - ( L(k) L(k+1) )*D(k)*( L(k) L(k+1) )**H
504 *                    = A - ( W(k) W(k+1) )*inv(D(k))*( W(k) W(k+1) )**H
505 *
506 *                 where L(k) and L(k+1) are the k-th and (k+1)-th
507 *                 columns of L
508 *
509                   D = DLAPY2( DBLE( A( K+1, K ) ),
510      $                DIMAG( A( K+1, K ) ) )
511                   D11 = DBLE( A( K+1, K+1 ) ) / D
512                   D22 = DBLE( A( K, K ) ) / D
513                   TT = ONE / ( D11*D22-ONE )
514                   D21 = A( K+1, K ) / D
515                   D = TT / D
516 *
517                   DO 80 J = K + 2, N
518                      WK = D*( D11*A( J, K )-D21*A( J, K+1 ) )
519                      WKP1 = D*( D22*A( J, K+1 )-DCONJG( D21 )*
520      $                      A( J, K ) )
521                      DO 70 I = J, N
522                         A( I, J ) = A( I, J ) - A( I, K )*DCONJG( WK ) -
523      $                              A( I, K+1 )*DCONJG( WKP1 )
524    70                CONTINUE
525                      A( J, K ) = WK
526                      A( J, K+1 ) = WKP1
527                      A( J, J ) = DCMPLXDBLE( A( J, J ) ), 0.0D+0 )
528    80             CONTINUE
529                END IF
530             END IF
531          END IF
532 *
533 *        Store details of the interchanges in IPIV
534 *
535          IF( KSTEP.EQ.1 ) THEN
536             IPIV( K ) = KP
537          ELSE
538             IPIV( K ) = -KP
539             IPIV( K+1 ) = -KP
540          END IF
541 *
542 *        Increase K and return to the start of the main loop
543 *
544          K = K + KSTEP
545          GO TO 50
546 *
547       END IF
548 *
549    90 CONTINUE
550       RETURN
551 *
552 *     End of ZHETF2
553 *
554       END