1 SUBROUTINE psgesvx( 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, IWORK, LIWORK, INFO )
12 CHARACTER EQUED, FACT, TRANS
13 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX, LIWORK,
18 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
19 $ DESCX( * ), IPIV( * ), IWORK( * )
20 REAL A( * ), AF( * ), B( * ), BERR( * ), C( * ),
21 $ ferr( * ), r( * ), work( * ), x( * )
407 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
408 $ LLD_, MB_, M_, NB_, N_, RSRC_
409 PARAMETER ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
410 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
411 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
413 PARAMETER ( ONE = 1.0e+0, zero = 0.0e+0 )
416 LOGICAL COLEQU, EQUIL, LQUERY, NOFACT, NOTRAN, ROWEQU
418 INTEGER CONWRK, I, IACOL, IAROW, IAFROW, IBROW, IBCOL,
419 $ icoffa, icoffb, icoffx, ictxt, idumm,
421 $ infequ, iroffa, iroffaf, iroffb,
422 $ iroffx, ixcol, ixrow, j, jja, jjb, jjx,
424 $ liwmin, lwmin, mycol, myrow, np, npcol, nprow,
425 $ nq, nqb, nrhsq, rfswrk
426 REAL AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,
430 INTEGER CDESC( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
437 $ sgebs2d, sgamn2d, sgamx2d
441 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
442 REAL PSLAMCH, PSLANGE
443 EXTERNAL iceil, ilcm, indxg2p, lsame, numroc, pslange,
447 INTRINSIC ichar,
max,
min, mod, real
453 ictxt = desca( ctxt_ )
454 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
459 IF( nprow.EQ.-1 )
THEN
462 CALL chk1mat( n, 3, n, 3, ia, ja, desca, 8, info )
463 IF( lsame( fact,
'F' ) )
464 $
CALL chk1mat( n, 3, n, 3, iaf, jaf, descaf, 12, info )
465 CALL chk1mat( n, 3, nrhs, 4, ib, jb, descb, 20, info )
466 CALL chk1mat( n, 3, nrhs, 4, ix, jx, descx, 24, info )
467 nofact = lsame( fact,
'N' )
468 equil = lsame( fact,
'E' )
469 notran = lsame( trans,
'N' )
470 IF( nofact .OR. equil )
THEN
475 rowequ = lsame( equed,
'R' ) .OR. lsame( equed,
'B' )
476 colequ = lsame( equed,
'C' ) .OR. lsame( equed,
'B' )
477 smlnum = pslamch( ictxt,
'Safe minimum' )
478 bignum = one / smlnum
481 iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
483 iafrow = indxg2p( iaf, descaf( mb_ ), myrow,
484 $ descaf( rsrc_ ), nprow )
485 ibrow = indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
487 ixrow = indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
489 iroffa = mod( ia-1, desca( mb_ ) )
490 iroffaf = mod( iaf-1, descaf( mb_ ) )
491 icoffa = mod( ja-1, desca( nb_ ) )
492 iroffb = mod( ib-1, descb( mb_ ) )
493 icoffb = mod( jb-1, descb( nb_ ) )
494 iroffx = mod( ix-1, descx( mb_ ) )
495 icoffx = mod( jx-1, descx( nb_ ) )
496 CALL infog2l( ia, ja, desca, nprow, npcol, myrow,
497 $ mycol, iia, jja, iarow, iacol )
498 np = numroc( n+iroffa, desca( mb_ ), myrow, iarow,
502 nq = numroc( n+icoffa, desca( nb_ ), mycol, iacol,
506 nqb = iceil( n+iroffa, desca( nb_ )*npcol )
507 lcm = ilcm( nprow, npcol )
509 conwrk = 2*np + 2*nq +
max( 2,
max( desca( nb_ )*
510 $
max( 1, iceil( nprow-1, npcol ) ), nq +
512 $
max( 1, iceil( npcol-1, nprow ) ) ) )
514 IF( lsame( trans,
'N' ) )
THEN
515 rfswrk = rfswrk + np + nq +
516 $ iceil( nqb, lcmq )*desca( nb_ )
517 ELSE IF( lsame( trans,
'T' ).OR.lsame( trans,
'C' ) )
THEN
518 rfswrk = rfswrk + np + nq
520 lwmin =
max( conwrk, rfswrk )
521 work( 1 ) = real( lwmin )
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 )
591 lquery = ( lwork.EQ.-1 .OR. liwork.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( liwork.LT.liwmin .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( liwork.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( liwork.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,
'PSGESVX', -info )
655 ELSE IF( lquery )
THEN
663 CALL psgeequ( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
665 IF( infequ.EQ.0 )
THEN
669 CALL pslaqge( 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_ ), work, ib, jb,
704 IF( mycol.EQ.ibcol )
THEN
705 CALL sgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( iib ),
708 CALL sgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( 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_ ) ) = work( i )*
714 $ b( i+( j-1 )*descb( lld_ ) )
719 IF( nofact.OR.equil )
THEN
723 CALL pslacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
725 CALL psgetrf( n, n, af, iaf, jaf, descaf, ipiv, info )
743 anorm = pslange( norm, n, n, a, ia, ja, desca, work )
747 CALL psgecon( norm, n, af, iaf, jaf, descaf, anorm, rcond, work,
748 $ lwork, iwork, liwork, info )
752 IF( rcond.LT.pslamch( ictxt,
'Epsilon' ) )
THEN
759 CALL pslacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
761 CALL psgetrs( trans, n, nrhs, af, iaf, jaf, descaf, ipiv, x, ix,
767 CALL psgerfs( 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, iwork, liwork, 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_ ), work, ix,
792 IF( mycol.EQ.ibcol )
THEN
793 CALL sgebs2d( ictxt,
'Rowwise',
' ', np, 1,
794 $ work( iix ), descx( lld_ ) )
796 CALL sgebr2d( ictxt,
'Rowwise',
' ', np, 1,
797 $ work( iix ), descx( lld_ ), myrow, ibcol )
800 DO 80 j = jjx, jjx+nrhsq-1
801 DO 70 i = iix, iix+np-1
802 x( i+( j-1 )*descx( lld_ ) ) = work( i )*
803 $ x( i+( j-1 )*descx( lld_ ) )
806 DO 90 j = jjx, jjx+nrhsq-1
807 ferr( j ) = ferr( j ) / colcnd
810 ELSE IF( rowequ )
THEN
811 DO 110 j = jjx, jjx+nrhsq-1
812 DO 100 i = iix, iix+np-1
813 x( i+( j-1 )*descx( lld_ ) ) = r( i )*
814 $ x( i+( j-1 )*descx( lld_ ) )
817 DO 120 j = jjx, jjx+nrhsq-1
818 ferr( j ) = ferr( j ) / rowcnd
822 work( 1 ) = real( lwmin )