LAPACK 3.11.0
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches

◆ 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).

Download ZLAHEF + dependencies [TGZ] [ZIP] [TXT]

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.
Author
Univ. of Tennessee
Univ. of California Berkeley
Univ. of Colorado Denver
NAG Ltd.
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: