LAPACK 3.12.1
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 174 of file zlahef.f.

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