 LAPACK  3.10.1 LAPACK: Linear Algebra PACKage

## ◆ zlahef()

 subroutine zlahef ( character UPLO, integer N, integer NB, integer KB, complex*16, dimension( lda, * ) A, integer LDA, integer, dimension( * ) IPIV, complex*16, dimension( ldw, * ) W, integer LDW, integer INFO )

ZLAHEF computes a partial factorization of a complex Hermitian indefinite matrix using the Bunch-Kaufman diagonal pivoting method (blocked algorithm, calling Level 3 BLAS).

Purpose:
``` ZLAHEF computes a partial factorization of a complex Hermitian
matrix A using the Bunch-Kaufman diagonal pivoting method. The
partial factorization has the form:

A  =  ( I  U12 ) ( A11  0  ) (  I      0     )  if UPLO = 'U', or:
( 0  U22 ) (  0   D  ) ( U12**H U22**H )

A  =  ( L11  0 ) (  D   0  ) ( L11**H L21**H )  if UPLO = 'L'
( L21  I ) (  0  A22 ) (  0      I     )

where the order of D is at most NB. The actual order is returned in
the argument KB, and is either NB or NB-1, or N if N <= NB.
Note that U**H denotes the conjugate transpose of U.

ZLAHEF is an auxiliary routine called by ZHETRF. It uses blocked code
(calling Level 3 BLAS) to update the submatrix A11 (if UPLO = 'U') or
A22 (if UPLO = 'L').```
Parameters
 [in] UPLO ``` UPLO is CHARACTER*1 Specifies whether the upper or lower triangular part of the Hermitian matrix A is stored: = 'U': Upper triangular = 'L': Lower triangular``` [in] N ``` N is INTEGER The order of the matrix A. N >= 0.``` [in] NB ``` NB is INTEGER The maximum number of columns of the matrix A that should be factored. NB should be at least 2 to allow for 2-by-2 pivot blocks.``` [out] KB ``` KB is INTEGER The number of columns of A that were actually factored. KB is either NB-1 or NB, or N if N <= NB.``` [in,out] A ``` A is COMPLEX*16 array, dimension (LDA,N) On entry, the Hermitian matrix A. If UPLO = 'U', the leading n-by-n upper triangular part of A contains the upper triangular part of the matrix A, and the strictly lower triangular part of A is not referenced. If UPLO = 'L', the leading n-by-n lower triangular part of A contains the lower triangular part of the matrix A, and the strictly upper triangular part of A is not referenced. On exit, A contains details of the partial factorization.``` [in] LDA ``` LDA is INTEGER The leading dimension of the array A. LDA >= max(1,N).``` [out] IPIV ``` IPIV is INTEGER array, dimension (N) Details of the interchanges and the block structure of D. If UPLO = 'U': Only the last KB elements of IPIV are set. If IPIV(k) > 0, then rows and columns k and IPIV(k) were interchanged and D(k,k) is a 1-by-1 diagonal block. If IPIV(k) = IPIV(k-1) < 0, then rows and columns k-1 and -IPIV(k) were interchanged and D(k-1:k,k-1:k) is a 2-by-2 diagonal block. If UPLO = 'L': Only the first KB elements of IPIV are set. If IPIV(k) > 0, then rows and columns k and IPIV(k) were interchanged and D(k,k) is a 1-by-1 diagonal block. If IPIV(k) = IPIV(k+1) < 0, then rows and columns k+1 and -IPIV(k) were interchanged and D(k:k+1,k:k+1) is a 2-by-2 diagonal block.``` [out] W ` W is COMPLEX*16 array, dimension (LDW,NB)` [in] LDW ``` LDW is INTEGER The leading dimension of the array W. LDW >= max(1,N).``` [out] INFO ``` INFO is INTEGER = 0: successful exit > 0: if INFO = k, D(k,k) is exactly zero. The factorization has been completed, but the block diagonal matrix D is exactly singular.```
Contributors:
```  December 2016,  Igor Kozachenko,
Computer Science Division,
University of California, Berkeley```

Definition at line 176 of file zlahef.f.

177 *
178 * -- LAPACK computational routine --
179 * -- LAPACK is a software package provided by Univ. of Tennessee, --
180 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
181 *
182 * .. Scalar Arguments ..
183  CHARACTER UPLO
184  INTEGER INFO, KB, LDA, LDW, N, NB
185 * ..
186 * .. Array Arguments ..
187  INTEGER IPIV( * )
188  COMPLEX*16 A( LDA, * ), W( LDW, * )
189 * ..
190 *
191 * =====================================================================
192 *
193 * .. Parameters ..
194  DOUBLE PRECISION ZERO, ONE
195  parameter( zero = 0.0d+0, one = 1.0d+0 )
196  COMPLEX*16 CONE
197  parameter( cone = ( 1.0d+0, 0.0d+0 ) )
198  DOUBLE PRECISION EIGHT, SEVTEN
199  parameter( eight = 8.0d+0, sevten = 17.0d+0 )
200 * ..
201 * .. Local Scalars ..
202  INTEGER IMAX, J, JB, JJ, JMAX, JP, K, KK, KKW, KP,
203  \$ KSTEP, KW
204  DOUBLE PRECISION ABSAKK, ALPHA, COLMAX, R1, ROWMAX, T
205  COMPLEX*16 D11, D21, D22, Z
206 * ..
207 * .. External Functions ..
208  LOGICAL LSAME
209  INTEGER IZAMAX
210  EXTERNAL lsame, izamax
211 * ..
212 * .. External Subroutines ..
213  EXTERNAL zcopy, zdscal, zgemm, zgemv, zlacgv, zswap
214 * ..
215 * .. Intrinsic Functions ..
216  INTRINSIC abs, dble, dconjg, dimag, max, min, sqrt
217 * ..
218 * .. Statement Functions ..
219  DOUBLE PRECISION CABS1
220 * ..
221 * .. Statement Function definitions ..
222  cabs1( z ) = abs( dble( z ) ) + abs( dimag( z ) )
223 * ..
224 * .. Executable Statements ..
225 *
226  info = 0
227 *
228 * Initialize ALPHA for use in choosing pivot block size.
229 *
230  alpha = ( one+sqrt( sevten ) ) / eight
231 *
232  IF( lsame( uplo, 'U' ) ) THEN
233 *
234 * Factorize the trailing columns of A using the upper triangle
235 * of A and working backwards, and compute the matrix W = U12*D
236 * for use in updating A11 (note that conjg(W) is actually stored)
237 *
238 * K is the main loop index, decreasing from N in steps of 1 or 2
239 *
240 * KW is the column of W which corresponds to column K of A
241 *
242  k = n
243  10 CONTINUE
244  kw = nb + k - n
245 *
246 * Exit from loop
247 *
248  IF( ( k.LE.n-nb+1 .AND. nb.LT.n ) .OR. k.LT.1 )
249  \$ GO TO 30
250 *
251  kstep = 1
252 *
253 * Copy column K of A to column KW of W and update it
254 *
255  CALL zcopy( k-1, a( 1, k ), 1, w( 1, kw ), 1 )
256  w( k, kw ) = dble( a( k, k ) )
257  IF( k.LT.n ) THEN
258  CALL zgemv( 'No transpose', k, n-k, -cone, a( 1, k+1 ), lda,
259  \$ w( k, kw+1 ), ldw, cone, w( 1, kw ), 1 )
260  w( k, kw ) = dble( w( k, kw ) )
261  END IF
262 *
263 * Determine rows and columns to be interchanged and whether
264 * a 1-by-1 or 2-by-2 pivot block will be used
265 *
266  absakk = abs( dble( w( k, kw ) ) )
267 *
268 * IMAX is the row-index of the largest off-diagonal element in
269 * column K, and COLMAX is its absolute value.
270 * Determine both COLMAX and IMAX.
271 *
272  IF( k.GT.1 ) THEN
273  imax = izamax( k-1, w( 1, kw ), 1 )
274  colmax = cabs1( w( imax, kw ) )
275  ELSE
276  colmax = zero
277  END IF
278 *
279  IF( max( absakk, colmax ).EQ.zero ) THEN
280 *
281 * Column K is zero or underflow: set INFO and continue
282 *
283  IF( info.EQ.0 )
284  \$ info = k
285  kp = k
286  a( k, k ) = dble( a( k, k ) )
287  ELSE
288 *
289 * ============================================================
290 *
291 * BEGIN pivot search
292 *
293 * Case(1)
294  IF( absakk.GE.alpha*colmax ) THEN
295 *
296 * no interchange, use 1-by-1 pivot block
297 *
298  kp = k
299  ELSE
300 *
301 * BEGIN pivot search along IMAX row
302 *
303 *
304 * Copy column IMAX to column KW-1 of W and update it
305 *
306  CALL zcopy( imax-1, a( 1, imax ), 1, w( 1, kw-1 ), 1 )
307  w( imax, kw-1 ) = dble( a( imax, imax ) )
308  CALL zcopy( k-imax, a( imax, imax+1 ), lda,
309  \$ w( imax+1, kw-1 ), 1 )
310  CALL zlacgv( k-imax, w( imax+1, kw-1 ), 1 )
311  IF( k.LT.n ) THEN
312  CALL zgemv( 'No transpose', k, n-k, -cone,
313  \$ a( 1, k+1 ), lda, w( imax, kw+1 ), ldw,
314  \$ cone, w( 1, kw-1 ), 1 )
315  w( imax, kw-1 ) = dble( w( imax, kw-1 ) )
316  END IF
317 *
318 * JMAX is the column-index of the largest off-diagonal
319 * element in row IMAX, and ROWMAX is its absolute value.
320 * Determine only ROWMAX.
321 *
322  jmax = imax + izamax( k-imax, w( imax+1, kw-1 ), 1 )
323  rowmax = cabs1( w( jmax, kw-1 ) )
324  IF( imax.GT.1 ) THEN
325  jmax = izamax( imax-1, w( 1, kw-1 ), 1 )
326  rowmax = max( rowmax, cabs1( w( jmax, kw-1 ) ) )
327  END IF
328 *
329 * Case(2)
330  IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
331 *
332 * no interchange, use 1-by-1 pivot block
333 *
334  kp = k
335 *
336 * Case(3)
337  ELSE IF( abs( dble( w( imax, kw-1 ) ) ).GE.alpha*rowmax )
338  \$ THEN
339 *
340 * interchange rows and columns K and IMAX, use 1-by-1
341 * pivot block
342 *
343  kp = imax
344 *
345 * copy column KW-1 of W to column KW of W
346 *
347  CALL zcopy( k, w( 1, kw-1 ), 1, w( 1, kw ), 1 )
348 *
349 * Case(4)
350  ELSE
351 *
352 * interchange rows and columns K-1 and IMAX, use 2-by-2
353 * pivot block
354 *
355  kp = imax
356  kstep = 2
357  END IF
358 *
359 *
360 * END pivot search along IMAX row
361 *
362  END IF
363 *
364 * END pivot search
365 *
366 * ============================================================
367 *
368 * KK is the column of A where pivoting step stopped
369 *
370  kk = k - kstep + 1
371 *
372 * KKW is the column of W which corresponds to column KK of A
373 *
374  kkw = nb + kk - n
375 *
376 * Interchange rows and columns KP and KK.
377 * Updated column KP is already stored in column KKW of W.
378 *
379  IF( kp.NE.kk ) THEN
380 *
381 * Copy non-updated column KK to column KP of submatrix A
382 * at step K. No need to copy element into column K
383 * (or K and K-1 for 2-by-2 pivot) of A, since these columns
384 * will be later overwritten.
385 *
386  a( kp, kp ) = dble( a( kk, kk ) )
387  CALL zcopy( kk-1-kp, a( kp+1, kk ), 1, a( kp, kp+1 ),
388  \$ lda )
389  CALL zlacgv( kk-1-kp, a( kp, kp+1 ), lda )
390  IF( kp.GT.1 )
391  \$ CALL zcopy( kp-1, a( 1, kk ), 1, a( 1, kp ), 1 )
392 *
393 * Interchange rows KK and KP in last K+1 to N columns of A
394 * (columns K (or K and K-1 for 2-by-2 pivot) of A will be
395 * later overwritten). Interchange rows KK and KP
396 * in last KKW to NB columns of W.
397 *
398  IF( k.LT.n )
399  \$ CALL zswap( n-k, a( kk, k+1 ), lda, a( kp, k+1 ),
400  \$ lda )
401  CALL zswap( n-kk+1, w( kk, kkw ), ldw, w( kp, kkw ),
402  \$ ldw )
403  END IF
404 *
405  IF( kstep.EQ.1 ) THEN
406 *
407 * 1-by-1 pivot block D(k): column kw of W now holds
408 *
409 * W(kw) = U(k)*D(k),
410 *
411 * where U(k) is the k-th column of U
412 *
413 * (1) Store subdiag. elements of column U(k)
414 * and 1-by-1 block D(k) in column k of A.
415 * (NOTE: Diagonal element U(k,k) is a UNIT element
416 * and not stored)
417 * A(k,k) := D(k,k) = W(k,kw)
418 * A(1:k-1,k) := U(1:k-1,k) = W(1:k-1,kw)/D(k,k)
419 *
420 * (NOTE: No need to use for Hermitian matrix
421 * A( K, K ) = DBLE( W( K, K) ) to separately copy diagonal
422 * element D(k,k) from W (potentially saves only one load))
423  CALL zcopy( k, w( 1, kw ), 1, a( 1, k ), 1 )
424  IF( k.GT.1 ) THEN
425 *
426 * (NOTE: No need to check if A(k,k) is NOT ZERO,
427 * since that was ensured earlier in pivot search:
428 * case A(k,k) = 0 falls into 2x2 pivot case(4))
429 *
430  r1 = one / dble( a( k, k ) )
431  CALL zdscal( k-1, r1, a( 1, k ), 1 )
432 *
433 * (2) Conjugate column W(kw)
434 *
435  CALL zlacgv( k-1, w( 1, kw ), 1 )
436  END IF
437 *
438  ELSE
439 *
440 * 2-by-2 pivot block D(k): columns kw and kw-1 of W now hold
441 *
442 * ( W(kw-1) W(kw) ) = ( U(k-1) U(k) )*D(k)
443 *
444 * where U(k) and U(k-1) are the k-th and (k-1)-th columns
445 * of U
446 *
447 * (1) Store U(1:k-2,k-1) and U(1:k-2,k) and 2-by-2
448 * block D(k-1:k,k-1:k) in columns k-1 and k of A.
449 * (NOTE: 2-by-2 diagonal block U(k-1:k,k-1:k) is a UNIT
450 * block and not stored)
451 * A(k-1:k,k-1:k) := D(k-1:k,k-1:k) = W(k-1:k,kw-1:kw)
452 * A(1:k-2,k-1:k) := U(1:k-2,k:k-1:k) =
453 * = W(1:k-2,kw-1:kw) * ( D(k-1:k,k-1:k)**(-1) )
454 *
455  IF( k.GT.2 ) THEN
456 *
457 * Factor out the columns of the inverse of 2-by-2 pivot
458 * block D, so that each column contains 1, to reduce the
459 * number of FLOPS when we multiply panel
460 * ( W(kw-1) W(kw) ) by this inverse, i.e. by D**(-1).
461 *
462 * D**(-1) = ( d11 cj(d21) )**(-1) =
463 * ( d21 d22 )
464 *
465 * = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) =
466 * ( (-d21) ( d11 ) )
467 *
468 * = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) *
469 *
470 * * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) =
471 * ( ( -1 ) ( d11/conj(d21) ) )
472 *
473 * = 1/(|d21|**2) * 1/(D22*D11-1) *
474 *
475 * * ( d21*( D11 ) conj(d21)*( -1 ) ) =
476 * ( ( -1 ) ( D22 ) )
477 *
478 * = (1/|d21|**2) * T * ( d21*( D11 ) conj(d21)*( -1 ) ) =
479 * ( ( -1 ) ( D22 ) )
480 *
481 * = ( (T/conj(d21))*( D11 ) (T/d21)*( -1 ) ) =
482 * ( ( -1 ) ( D22 ) )
483 *
484 * = ( conj(D21)*( D11 ) D21*( -1 ) )
485 * ( ( -1 ) ( D22 ) ),
486 *
487 * where D11 = d22/d21,
488 * D22 = d11/conj(d21),
489 * D21 = T/d21,
490 * T = 1/(D22*D11-1).
491 *
492 * (NOTE: No need to check for division by ZERO,
493 * since that was ensured earlier in pivot search:
494 * (a) d21 != 0, since in 2x2 pivot case(4)
495 * |d21| should be larger than |d11| and |d22|;
496 * (b) (D22*D11 - 1) != 0, since from (a),
497 * both |D11| < 1, |D22| < 1, hence |D22*D11| << 1.)
498 *
499  d21 = w( k-1, kw )
500  d11 = w( k, kw ) / dconjg( d21 )
501  d22 = w( k-1, kw-1 ) / d21
502  t = one / ( dble( d11*d22 )-one )
503  d21 = t / d21
504 *
505 * Update elements in columns A(k-1) and A(k) as
506 * dot products of rows of ( W(kw-1) W(kw) ) and columns
507 * of D**(-1)
508 *
509  DO 20 j = 1, k - 2
510  a( j, k-1 ) = d21*( d11*w( j, kw-1 )-w( j, kw ) )
511  a( j, k ) = dconjg( d21 )*
512  \$ ( d22*w( j, kw )-w( j, kw-1 ) )
513  20 CONTINUE
514  END IF
515 *
516 * Copy D(k) to A
517 *
518  a( k-1, k-1 ) = w( k-1, kw-1 )
519  a( k-1, k ) = w( k-1, kw )
520  a( k, k ) = w( k, kw )
521 *
522 * (2) Conjugate columns W(kw) and W(kw-1)
523 *
524  CALL zlacgv( k-1, w( 1, kw ), 1 )
525  CALL zlacgv( k-2, w( 1, kw-1 ), 1 )
526 *
527  END IF
528 *
529  END IF
530 *
531 * Store details of the interchanges in IPIV
532 *
533  IF( kstep.EQ.1 ) THEN
534  ipiv( k ) = kp
535  ELSE
536  ipiv( k ) = -kp
537  ipiv( k-1 ) = -kp
538  END IF
539 *
540 * Decrease K and return to the start of the main loop
541 *
542  k = k - kstep
543  GO TO 10
544 *
545  30 CONTINUE
546 *
547 * Update the upper triangle of A11 (= A(1:k,1:k)) as
548 *
549 * A11 := A11 - U12*D*U12**H = A11 - U12*W**H
550 *
551 * computing blocks of NB columns at a time (note that conjg(W) is
552 * actually stored)
553 *
554  DO 50 j = ( ( k-1 ) / nb )*nb + 1, 1, -nb
555  jb = min( nb, k-j+1 )
556 *
557 * Update the upper triangle of the diagonal block
558 *
559  DO 40 jj = j, j + jb - 1
560  a( jj, jj ) = dble( a( jj, jj ) )
561  CALL zgemv( 'No transpose', jj-j+1, n-k, -cone,
562  \$ a( j, k+1 ), lda, w( jj, kw+1 ), ldw, cone,
563  \$ a( j, jj ), 1 )
564  a( jj, jj ) = dble( a( jj, jj ) )
565  40 CONTINUE
566 *
567 * Update the rectangular superdiagonal block
568 *
569  CALL zgemm( 'No transpose', 'Transpose', j-1, jb, n-k,
570  \$ -cone, a( 1, k+1 ), lda, w( j, kw+1 ), ldw,
571  \$ cone, a( 1, j ), lda )
572  50 CONTINUE
573 *
574 * Put U12 in standard form by partially undoing the interchanges
575 * in columns k+1:n looping backwards from k+1 to n
576 *
577  j = k + 1
578  60 CONTINUE
579 *
580 * Undo the interchanges (if any) of rows JJ and JP at each
581 * step J
582 *
583 * (Here, J is a diagonal index)
584  jj = j
585  jp = ipiv( j )
586  IF( jp.LT.0 ) THEN
587  jp = -jp
588 * (Here, J is a diagonal index)
589  j = j + 1
590  END IF
591 * (NOTE: Here, J is used to determine row length. Length N-J+1
592 * of the rows to swap back doesn't include diagonal element)
593  j = j + 1
594  IF( jp.NE.jj .AND. j.LE.n )
595  \$ CALL zswap( n-j+1, a( jp, j ), lda, a( jj, j ), lda )
596  IF( j.LT.n )
597  \$ GO TO 60
598 *
599 * Set KB to the number of columns factorized
600 *
601  kb = n - k
602 *
603  ELSE
604 *
605 * Factorize the leading columns of A using the lower triangle
606 * of A and working forwards, and compute the matrix W = L21*D
607 * for use in updating A22 (note that conjg(W) is actually stored)
608 *
609 * K is the main loop index, increasing from 1 in steps of 1 or 2
610 *
611  k = 1
612  70 CONTINUE
613 *
614 * Exit from loop
615 *
616  IF( ( k.GE.nb .AND. nb.LT.n ) .OR. k.GT.n )
617  \$ GO TO 90
618 *
619  kstep = 1
620 *
621 * Copy column K of A to column K of W and update it
622 *
623  w( k, k ) = dble( a( k, k ) )
624  IF( k.LT.n )
625  \$ CALL zcopy( n-k, a( k+1, k ), 1, w( k+1, k ), 1 )
626  CALL zgemv( 'No transpose', n-k+1, k-1, -cone, a( k, 1 ), lda,
627  \$ w( k, 1 ), ldw, cone, w( k, k ), 1 )
628  w( k, k ) = dble( w( k, k ) )
629 *
630 * Determine rows and columns to be interchanged and whether
631 * a 1-by-1 or 2-by-2 pivot block will be used
632 *
633  absakk = abs( dble( w( k, k ) ) )
634 *
635 * IMAX is the row-index of the largest off-diagonal element in
636 * column K, and COLMAX is its absolute value.
637 * Determine both COLMAX and IMAX.
638 *
639  IF( k.LT.n ) THEN
640  imax = k + izamax( n-k, w( k+1, k ), 1 )
641  colmax = cabs1( w( imax, k ) )
642  ELSE
643  colmax = zero
644  END IF
645 *
646  IF( max( absakk, colmax ).EQ.zero ) THEN
647 *
648 * Column K is zero or underflow: set INFO and continue
649 *
650  IF( info.EQ.0 )
651  \$ info = k
652  kp = k
653  a( k, k ) = dble( a( k, k ) )
654  ELSE
655 *
656 * ============================================================
657 *
658 * BEGIN pivot search
659 *
660 * Case(1)
661  IF( absakk.GE.alpha*colmax ) THEN
662 *
663 * no interchange, use 1-by-1 pivot block
664 *
665  kp = k
666  ELSE
667 *
668 * BEGIN pivot search along IMAX row
669 *
670 *
671 * Copy column IMAX to column K+1 of W and update it
672 *
673  CALL zcopy( imax-k, a( imax, k ), lda, w( k, k+1 ), 1 )
674  CALL zlacgv( imax-k, w( k, k+1 ), 1 )
675  w( imax, k+1 ) = dble( a( imax, imax ) )
676  IF( imax.LT.n )
677  \$ CALL zcopy( n-imax, a( imax+1, imax ), 1,
678  \$ w( imax+1, k+1 ), 1 )
679  CALL zgemv( 'No transpose', n-k+1, k-1, -cone, a( k, 1 ),
680  \$ lda, w( imax, 1 ), ldw, cone, w( k, k+1 ),
681  \$ 1 )
682  w( imax, k+1 ) = dble( w( imax, k+1 ) )
683 *
684 * JMAX is the column-index of the largest off-diagonal
685 * element in row IMAX, and ROWMAX is its absolute value.
686 * Determine only ROWMAX.
687 *
688  jmax = k - 1 + izamax( imax-k, w( k, k+1 ), 1 )
689  rowmax = cabs1( w( jmax, k+1 ) )
690  IF( imax.LT.n ) THEN
691  jmax = imax + izamax( n-imax, w( imax+1, k+1 ), 1 )
692  rowmax = max( rowmax, cabs1( w( jmax, k+1 ) ) )
693  END IF
694 *
695 * Case(2)
696  IF( absakk.GE.alpha*colmax*( colmax / rowmax ) ) THEN
697 *
698 * no interchange, use 1-by-1 pivot block
699 *
700  kp = k
701 *
702 * Case(3)
703  ELSE IF( abs( dble( w( imax, k+1 ) ) ).GE.alpha*rowmax )
704  \$ THEN
705 *
706 * interchange rows and columns K and IMAX, use 1-by-1
707 * pivot block
708 *
709  kp = imax
710 *
711 * copy column K+1 of W to column K of W
712 *
713  CALL zcopy( n-k+1, w( k, k+1 ), 1, w( k, k ), 1 )
714 *
715 * Case(4)
716  ELSE
717 *
718 * interchange rows and columns K+1 and IMAX, use 2-by-2
719 * pivot block
720 *
721  kp = imax
722  kstep = 2
723  END IF
724 *
725 *
726 * END pivot search along IMAX row
727 *
728  END IF
729 *
730 * END pivot search
731 *
732 * ============================================================
733 *
734 * KK is the column of A where pivoting step stopped
735 *
736  kk = k + kstep - 1
737 *
738 * Interchange rows and columns KP and KK.
739 * Updated column KP is already stored in column KK of W.
740 *
741  IF( kp.NE.kk ) THEN
742 *
743 * Copy non-updated column KK to column KP of submatrix A
744 * at step K. No need to copy element into column K
745 * (or K and K+1 for 2-by-2 pivot) of A, since these columns
746 * will be later overwritten.
747 *
748  a( kp, kp ) = dble( a( kk, kk ) )
749  CALL zcopy( kp-kk-1, a( kk+1, kk ), 1, a( kp, kk+1 ),
750  \$ lda )
751  CALL zlacgv( kp-kk-1, a( kp, kk+1 ), lda )
752  IF( kp.LT.n )
753  \$ CALL zcopy( n-kp, a( kp+1, kk ), 1, a( kp+1, kp ), 1 )
754 *
755 * Interchange rows KK and KP in first K-1 columns of A
756 * (columns K (or K and K+1 for 2-by-2 pivot) of A will be
757 * later overwritten). Interchange rows KK and KP
758 * in first KK columns of W.
759 *
760  IF( k.GT.1 )
761  \$ CALL zswap( k-1, a( kk, 1 ), lda, a( kp, 1 ), lda )
762  CALL zswap( kk, w( kk, 1 ), ldw, w( kp, 1 ), ldw )
763  END IF
764 *
765  IF( kstep.EQ.1 ) THEN
766 *
767 * 1-by-1 pivot block D(k): column k of W now holds
768 *
769 * W(k) = L(k)*D(k),
770 *
771 * where L(k) is the k-th column of L
772 *
773 * (1) Store subdiag. elements of column L(k)
774 * and 1-by-1 block D(k) in column k of A.
775 * (NOTE: Diagonal element L(k,k) is a UNIT element
776 * and not stored)
777 * A(k,k) := D(k,k) = W(k,k)
778 * A(k+1:N,k) := L(k+1:N,k) = W(k+1:N,k)/D(k,k)
779 *
780 * (NOTE: No need to use for Hermitian matrix
781 * A( K, K ) = DBLE( W( K, K) ) to separately copy diagonal
782 * element D(k,k) from W (potentially saves only one load))
783  CALL zcopy( n-k+1, w( k, k ), 1, a( k, k ), 1 )
784  IF( k.LT.n ) THEN
785 *
786 * (NOTE: No need to check if A(k,k) is NOT ZERO,
787 * since that was ensured earlier in pivot search:
788 * case A(k,k) = 0 falls into 2x2 pivot case(4))
789 *
790  r1 = one / dble( a( k, k ) )
791  CALL zdscal( n-k, r1, a( k+1, k ), 1 )
792 *
793 * (2) Conjugate column W(k)
794 *
795  CALL zlacgv( n-k, w( k+1, k ), 1 )
796  END IF
797 *
798  ELSE
799 *
800 * 2-by-2 pivot block D(k): columns k and k+1 of W now hold
801 *
802 * ( W(k) W(k+1) ) = ( L(k) L(k+1) )*D(k)
803 *
804 * where L(k) and L(k+1) are the k-th and (k+1)-th columns
805 * of L
806 *
807 * (1) Store L(k+2:N,k) and L(k+2:N,k+1) and 2-by-2
808 * block D(k:k+1,k:k+1) in columns k and k+1 of A.
809 * (NOTE: 2-by-2 diagonal block L(k:k+1,k:k+1) is a UNIT
810 * block and not stored)
811 * A(k:k+1,k:k+1) := D(k:k+1,k:k+1) = W(k:k+1,k:k+1)
812 * A(k+2:N,k:k+1) := L(k+2:N,k:k+1) =
813 * = W(k+2:N,k:k+1) * ( D(k:k+1,k:k+1)**(-1) )
814 *
815  IF( k.LT.n-1 ) THEN
816 *
817 * Factor out the columns of the inverse of 2-by-2 pivot
818 * block D, so that each column contains 1, to reduce the
819 * number of FLOPS when we multiply panel
820 * ( W(kw-1) W(kw) ) by this inverse, i.e. by D**(-1).
821 *
822 * D**(-1) = ( d11 cj(d21) )**(-1) =
823 * ( d21 d22 )
824 *
825 * = 1/(d11*d22-|d21|**2) * ( ( d22) (-cj(d21) ) ) =
826 * ( (-d21) ( d11 ) )
827 *
828 * = 1/(|d21|**2) * 1/((d11/cj(d21))*(d22/d21)-1) *
829 *
830 * * ( d21*( d22/d21 ) conj(d21)*( - 1 ) ) =
831 * ( ( -1 ) ( d11/conj(d21) ) )
832 *
833 * = 1/(|d21|**2) * 1/(D22*D11-1) *
834 *
835 * * ( d21*( D11 ) conj(d21)*( -1 ) ) =
836 * ( ( -1 ) ( D22 ) )
837 *
838 * = (1/|d21|**2) * T * ( d21*( D11 ) conj(d21)*( -1 ) ) =
839 * ( ( -1 ) ( D22 ) )
840 *
841 * = ( (T/conj(d21))*( D11 ) (T/d21)*( -1 ) ) =
842 * ( ( -1 ) ( D22 ) )
843 *
844 * = ( conj(D21)*( D11 ) D21*( -1 ) )
845 * ( ( -1 ) ( D22 ) ),
846 *
847 * where D11 = d22/d21,
848 * D22 = d11/conj(d21),
849 * D21 = T/d21,
850 * T = 1/(D22*D11-1).
851 *
852 * (NOTE: No need to check for division by ZERO,
853 * since that was ensured earlier in pivot search:
854 * (a) d21 != 0, since in 2x2 pivot case(4)
855 * |d21| should be larger than |d11| and |d22|;
856 * (b) (D22*D11 - 1) != 0, since from (a),
857 * both |D11| < 1, |D22| < 1, hence |D22*D11| << 1.)
858 *
859  d21 = w( k+1, k )
860  d11 = w( k+1, k+1 ) / d21
861  d22 = w( k, k ) / dconjg( d21 )
862  t = one / ( dble( d11*d22 )-one )
863  d21 = t / d21
864 *
865 * Update elements in columns A(k) and A(k+1) as
866 * dot products of rows of ( W(k) W(k+1) ) and columns
867 * of D**(-1)
868 *
869  DO 80 j = k + 2, n
870  a( j, k ) = dconjg( d21 )*
871  \$ ( d11*w( j, k )-w( j, k+1 ) )
872  a( j, k+1 ) = d21*( d22*w( j, k+1 )-w( j, k ) )
873  80 CONTINUE
874  END IF
875 *
876 * Copy D(k) to A
877 *
878  a( k, k ) = w( k, k )
879  a( k+1, k ) = w( k+1, k )
880  a( k+1, k+1 ) = w( k+1, k+1 )
881 *
882 * (2) Conjugate columns W(k) and W(k+1)
883 *
884  CALL zlacgv( n-k, w( k+1, k ), 1 )
885  CALL zlacgv( n-k-1, w( k+2, k+1 ), 1 )
886 *
887  END IF
888 *
889  END IF
890 *
891 * Store details of the interchanges in IPIV
892 *
893  IF( kstep.EQ.1 ) THEN
894  ipiv( k ) = kp
895  ELSE
896  ipiv( k ) = -kp
897  ipiv( k+1 ) = -kp
898  END IF
899 *
900 * Increase K and return to the start of the main loop
901 *
902  k = k + kstep
903  GO TO 70
904 *
905  90 CONTINUE
906 *
907 * Update the lower triangle of A22 (= A(k:n,k:n)) as
908 *
909 * A22 := A22 - L21*D*L21**H = A22 - L21*W**H
910 *
911 * computing blocks of NB columns at a time (note that conjg(W) is
912 * actually stored)
913 *
914  DO 110 j = k, n, nb
915  jb = min( nb, n-j+1 )
916 *
917 * Update the lower triangle of the diagonal block
918 *
919  DO 100 jj = j, j + jb - 1
920  a( jj, jj ) = dble( a( jj, jj ) )
921  CALL zgemv( 'No transpose', j+jb-jj, k-1, -cone,
922  \$ a( jj, 1 ), lda, w( jj, 1 ), ldw, cone,
923  \$ a( jj, jj ), 1 )
924  a( jj, jj ) = dble( a( jj, jj ) )
925  100 CONTINUE
926 *
927 * Update the rectangular subdiagonal block
928 *
929  IF( j+jb.LE.n )
930  \$ CALL zgemm( 'No transpose', 'Transpose', n-j-jb+1, jb,
931  \$ k-1, -cone, a( j+jb, 1 ), lda, w( j, 1 ),
932  \$ ldw, cone, a( j+jb, j ), lda )
933  110 CONTINUE
934 *
935 * Put L21 in standard form by partially undoing the interchanges
936 * of rows in columns 1:k-1 looping backwards from k-1 to 1
937 *
938  j = k - 1
939  120 CONTINUE
940 *
941 * Undo the interchanges (if any) of rows JJ and JP at each
942 * step J
943 *
944 * (Here, J is a diagonal index)
945  jj = j
946  jp = ipiv( j )
947  IF( jp.LT.0 ) THEN
948  jp = -jp
949 * (Here, J is a diagonal index)
950  j = j - 1
951  END IF
952 * (NOTE: Here, J is used to determine row length. Length J
953 * of the rows to swap back doesn't include diagonal element)
954  j = j - 1
955  IF( jp.NE.jj .AND. j.GE.1 )
956  \$ CALL zswap( j, a( jp, 1 ), lda, a( jj, 1 ), lda )
957  IF( j.GT.1 )
958  \$ GO TO 120
959 *
960 * Set KB to the number of columns factorized
961 *
962  kb = k - 1
963 *
964  END IF
965  RETURN
966 *
967 * End of ZLAHEF
968 *
integer function izamax(N, ZX, INCX)
IZAMAX
Definition: izamax.f:71
logical function lsame(CA, CB)
LSAME
Definition: lsame.f:53
subroutine zswap(N, ZX, INCX, ZY, INCY)
ZSWAP
Definition: zswap.f:81
subroutine zdscal(N, DA, ZX, INCX)
ZDSCAL
Definition: zdscal.f:78
subroutine zcopy(N, ZX, INCX, ZY, INCY)
ZCOPY
Definition: zcopy.f:81
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
subroutine zlacgv(N, X, INCX)
ZLACGV conjugates a complex vector.
Definition: zlacgv.f:74
Here is the call graph for this function:
Here is the caller graph for this function: