1 SUBROUTINE pcgesvx( FACT, TRANS, N, NRHS, A, IA, JA, DESCA, AF,
2 $ IAF, JAF, DESCAF, IPIV, EQUED, R, C, B, IB,
3 $ JB, DESCB, X, IX, JX, DESCX, RCOND, FERR,
4 $ BERR, WORK, LWORK, RWORK, LRWORK, INFO )
12 CHARACTER EQUED, FACT, TRANS
13 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX, LRWORK,
18 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
19 $ DESCX( * ), IPIV( * )
20 REAL BERR( * ), C( * ), FERR( * ), R( * ),
22 COMPLEX A( * ), AF( * ), B( * ), WORK( * ), X( * )
408 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
409 $ LLD_, MB_, M_, NB_, N_, RSRC_
410 PARAMETER ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
411 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
412 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
414 PARAMETER ( ONE = 1.0e+0, zero = 0.0e+0 )
417 LOGICAL COLEQU, EQUIL, LQUERY, NOFACT, NOTRAN, ROWEQU
419 INTEGER CONWRK, I, IACOL, IAROW, IAFROW, IBROW, IBCOL,
420 $ icoffa, icoffb, icoffx, ictxt, idumm,
422 $ infequ, iroffa, iroffaf, iroffb,
423 $ iroffx, ixcol, ixrow, j, jja, jjb, jjx,
425 $ lrwmin, lwmin, mycol, myrow, np, npcol, nprow,
426 $ nq, nqb, nrhsq, rfswrk
427 REAL AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,
431 INTEGER CDESC( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
438 $ sgebs2d, sgamn2d, sgamx2d
442 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
443 REAL PSLAMCH, PCLANGE
444 EXTERNAL iceil, ilcm, indxg2p, lsame, numroc, pclange,
448 INTRINSIC ichar,
max,
min, mod, real
454 ictxt = desca( ctxt_ )
455 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
460 IF( nprow.EQ.-1 )
THEN
463 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 8, info )
464 IF( lsame( fact,
'F' ) )
465 $
CALL chk1mat( n, 3, n, 3, iaf, jaf, descaf, 12, info )
466 CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 20, info )
467 CALL chk1mat( n, 3, nrhs, 4, ix, jx, descx, 24, info )
468 nofact = lsame( fact,
'N' )
469 equil = lsame( fact,
'E' )
470 notran = lsame( trans,
'N' )
471 IF( nofact .OR. equil )
THEN
476 rowequ = lsame( equed,
'R' ) .OR. lsame( equed,
'B' )
477 colequ = lsame( equed,
'C' ) .OR. lsame( equed,
'B' )
478 smlnum = pslamch( ictxt,
'Safe minimum' )
479 bignum = one / smlnum
482 iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
484 iafrow = indxg2p( iaf, descaf( mb_ ), myrow,
485 $ descaf( rsrc_ ), nprow )
486 ibrow = indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
488 ixrow = indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
490 iroffa = mod( ia-1, desca( mb_ ) )
491 iroffaf = mod( iaf-1, descaf( mb_ ) )
492 icoffa = mod( ja-1, desca( nb_ ) )
493 iroffb = mod( ib-1, descb( mb_ ) )
494 icoffb = mod( jb-1, descb( nb_ ) )
495 iroffx = mod( ix-1, descx( mb_ ) )
496 icoffx = mod( jx-1, descx( nb_ ) )
497 CALL infog2l( ia, ja, desca, nprow, npcol, myrow,
498 $ mycol, iia, jja, iarow, iacol )
499 np = numroc( n+iroffa, desca( mb_ ), myrow, iarow,
503 nq = numroc( n+icoffa, desca( nb_ ), mycol, iacol,
507 nqb = iceil( n+iroffa, desca( nb_ )*npcol )
508 lcm = ilcm( nprow, npcol )
510 conwrk = 2*np + 2*nq +
max( 2,
max( desca( nb_ )*
511 $
max( 1, iceil( nprow-1, npcol ) ), nq +
513 $
max( 1, iceil( npcol-1, nprow ) ) ) )
515 IF( lsame( trans,
'N' ) )
THEN
516 rfswrk = rfswrk + np + nq +
517 $ iceil( nqb, lcmq )*desca( nb_ )
518 ELSE IF( lsame( trans,
'T' ).OR.lsame( trans,
'C' ) )
THEN
519 rfswrk = rfswrk + np + nq
521 lwmin =
max( conwrk, rfswrk )
522 lrwmin =
max( 2*nq, np )
523 rwork( 1 ) = real( lrwmin )
524 IF( .NOT.nofact .AND. .NOT.equil .AND.
525 $ .NOT.lsame( fact,
'F' ) )
THEN
527 ELSE IF( .NOT.notran .AND. .NOT.lsame( trans,
'T' ) .AND.
528 $ .NOT. lsame( trans,
'C' ) )
THEN
530 ELSE IF( iroffa.NE.0 )
THEN
532 ELSE IF( icoffa.NE.0 .OR. iroffa.NE.icoffa )
THEN
534 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
536 ELSE IF( iafrow.NE.iarow )
THEN
538 ELSE IF( iroffaf.NE.0 )
THEN
540 ELSE IF( ictxt.NE.descaf( ctxt_ ) )
THEN
542 ELSE IF( lsame( fact,
'F' ) .AND. .NOT.
543 $ ( rowequ .OR. colequ .OR. lsame( equed,
'N' ) ) )
THEN
549 DO 10 j = iia, iia + np - 1
550 rcmin =
min( rcmin, r( j ) )
551 rcmax =
max( rcmax, r( j ) )
553 CALL sgamn2d( ictxt,
'Columnwise',
' ', 1, 1, rcmin,
554 $ 1, idumm, idumm, -1, -1, mycol )
555 CALL sgamx2d( ictxt,
'Columnwise',
' ', 1, 1, rcmax,
556 $ 1, idumm, idumm, -1, -1, mycol )
557 IF( rcmin.LE.zero )
THEN
559 ELSE IF( n.GT.0 )
THEN
560 rowcnd =
max( rcmin, smlnum ) /
561 $
min( rcmax, bignum )
566 IF( colequ .AND. info.EQ.0 )
THEN
569 DO 20 j = jja, jja+nq-1
570 rcmin =
min( rcmin, c( j ) )
571 rcmax =
max( rcmax, c( j ) )
573 CALL sgamn2d( ictxt,
'Rowwise',
' ', 1, 1, rcmin,
574 $ 1, idumm, idumm, -1, -1, mycol )
575 CALL sgamx2d( ictxt,
'Rowwise',
' ', 1, 1, rcmax,
576 $ 1, idumm, idumm, -1, -1, mycol )
577 IF( rcmin.LE.zero )
THEN
579 ELSE IF( n.GT.0 )
THEN
580 colcnd =
max( rcmin, smlnum ) /
581 $
min( rcmax, bignum )
589 work( 1 ) = real( lwmin )
590 rwork( 1 ) = real( lrwmin )
591 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
593 IF( ibrow.NE.iarow )
THEN
595 ELSE IF( ixrow.NE.ibrow )
THEN
597 ELSE IF( descb( mb_ ).NE.desca( nb_ ) )
THEN
599 ELSE IF( ictxt.NE.descb( ctxt_ ) )
THEN
601 ELSE IF( descx( mb_ ).NE.desca( nb_ ) )
THEN
603 ELSE IF( ictxt.NE.descx( ctxt_ ) )
THEN
605 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
607 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery )
THEN
610 idum1( 1 ) = ichar( fact )
612 idum1( 2 ) = ichar( trans )
614 IF( lsame( fact,
'F' ) )
THEN
615 idum1( 3 ) = ichar( equed )
617 IF( lwork.EQ.-1 )
THEN
623 IF( lrwork.EQ.-1 )
THEN
629 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3,
630 $ nrhs, 4, ib, jb, descb, 20, 5, idum1,
633 IF( lwork.EQ.-1 )
THEN
639 IF( lrwork.EQ.-1 )
THEN
645 CALL pchk2mat( n, 3, n, 3, ia, ja, desca, 8, n, 3,
646 $ nrhs, 4, ib, jb, descb, 20, 4, idum1,
653 CALL pxerbla( ictxt,
'PCGESVX', -info )
655 ELSE IF( lquery )
THEN
663 CALL pcgeequ( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
665 IF( infequ.EQ.0 )
THEN
669 CALL pclaqge( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
671 rowequ = lsame( equed,
'R' ) .OR. lsame( equed,
'B' )
672 colequ = lsame( equed,
'C' ) .OR. lsame( equed,
'B' )
678 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol, iib,
679 $ jjb, ibrow, ibcol )
680 np = numroc( n+iroffb, descb( mb_ ), myrow, ibrow, nprow )
681 nrhsq = numroc( nrhs+icoffb, descb( nb_ ), mycol, ibcol, npcol )
685 $ nrhsq = nrhsq-icoffb
689 DO 40 j = jjb, jjb+nrhsq-1
690 DO 30 i = iib, iib+np-1
691 b( i+( j-1 )*descb( lld_ ) ) = r( i )*
692 $ b( i+( j-1 )*descb( lld_ ) )
696 ELSE IF( colequ )
THEN
700 CALL descset( cdesc, 1, n+icoffa, 1, desca( nb_ ), myrow,
702 CALL pscopy( n, c, 1, ja, cdesc, cdesc( lld_ ), rwork, ib, jb,
704 IF( mycol.EQ.ibcol )
THEN
705 CALL sgebs2d( ictxt,
'Rowwise',
' ', np, 1, rwork( iib ),
708 CALL sgebr2d( ictxt,
'Rowwise',
' ', np, 1, rwork( iib ),
709 $ descb( lld_ ), myrow, ibcol )
711 DO 60 j = jjb, jjb+nrhsq-1
712 DO 50 i = iib, iib+np-1
713 b( i+( j-1 )*descb( lld_ ) ) = rwork( i )*
714 $ b( i+( j-1 )*descb( lld_ ) )
719 IF( nofact.OR.equil )
THEN
723 CALL pclacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
725 CALL pcgetrf( n, n, af, iaf, jaf, descaf, ipiv, info )
743 anorm = pclange( norm, n, n, a, ia, ja, desca, rwork )
747 CALL pcgecon( norm, n, af, iaf, jaf, descaf, anorm, rcond, work,
748 $ lwork, rwork, lrwork, info )
752 IF( rcond.LT.pslamch( ictxt,
'Epsilon' ) )
THEN
759 CALL pclacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
761 CALL pcgetrs( trans, n, nrhs, af, iaf, jaf, descaf, ipiv, x, ix,
767 CALL pcgerfs( trans, n, nrhs, a, ia, ja, desca, af, iaf, jaf,
768 $ descaf, ipiv, b, ib, jb, descb, x, ix, jx, descx,
769 $ ferr, berr, work, lwork, rwork, lrwork, info )
774 CALL infog2l( ix, jx, descx, nprow, npcol, myrow, mycol, iix,
775 $ jjx, ixrow, ixcol )
776 np = numroc( n+iroffx, descx( mb_ ), myrow, ixrow, nprow )
777 nrhsq = numroc( nrhs+icoffx, descx( nb_ ), mycol, ixcol, npcol )
781 $ nrhsq = nrhsq-icoffx
788 CALL descset( cdesc, 1, n+icoffa, 1, desca( nb_ ), myrow,
790 CALL pscopy( n, c, 1, ja, cdesc, cdesc( lld_ ), rwork, ix,
792 IF( mycol.EQ.ibcol )
THEN
793 CALL sgebs2d( ictxt,
'Rowwise',
' ', np, 1,
794 $ rwork( iix ), descx( lld_ ) )
796 CALL sgebr2d( ictxt,
'Rowwise',
' ', np, 1,
797 $ rwork( iix ), descx( lld_ ), myrow,
801 DO 80 j = jjx, jjx+nrhsq-1
802 DO 70 i = iix, iix+np-1
803 x( i+( j-1 )*descx( lld_ ) ) = rwork( i )*
804 $ x( i+( j-1 )*descx( lld_ ) )
807 DO 90 j = jjx, jjx+nrhsq-1
808 ferr( j ) = ferr( j ) / colcnd
811 ELSE IF( rowequ )
THEN
812 DO 110 j = jjx, jjx+nrhsq-1
813 DO 100 i = iix, iix+np-1
814 x( i+( j-1 )*descx( lld_ ) ) = r( i )*
815 $ x( i+( j-1 )*descx( lld_ ) )
818 DO 120 j = jjx, jjx+nrhsq-1
819 ferr( j ) = ferr( j ) / rowcnd
823 work( 1 ) = real( lwmin )
824 rwork( 1 ) = real( lrwmin )