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

◆ clahef()

subroutine clahef ( character uplo,
integer n,
integer nb,
integer kb,
complex, dimension( lda, * ) a,
integer lda,
integer, dimension( * ) ipiv,
complex, dimension( ldw, * ) w,
integer ldw,
integer info )

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

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

Purpose:
!>
!> CLAHEF 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.
!>
!> CLAHEF is an auxiliary routine called by CHETRF. 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 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 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:
!>
!>  November 2013,  Igor Kozachenko,
!>                  Computer Science Division,
!>                  University of California, Berkeley
!> 

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