1 SUBROUTINE pzgesvx( 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,
15 DOUBLE PRECISION RCOND
18 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
19 $ DESCX( * ), IPIV( * )
20 DOUBLE PRECISION BERR( * ), C( * ), FERR( * ), R( * ),
22 COMPLEX*16 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 )
413 DOUBLE PRECISION ONE, ZERO
414 PARAMETER ( ONE = 1.0d+0, zero = 0.0d+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 DOUBLE PRECISION AMAX, ANORM, BIGNUM, COLCND, RCMAX, RCMIN,
431 INTEGER CDESC( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
435 $ dgebr2d, dgebs2d, dgamn2d,
442 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
443 DOUBLE PRECISION PDLAMCH, PZLANGE
444 EXTERNAL iceil, ilcm, indxg2p, lsame, numroc, pzlange,
448 INTRINSIC dble, ichar,
max,
min, mod
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 = pdlamch( 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 ) = dble( 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 dgamn2d( ictxt,
'Columnwise',
' ', 1, 1, rcmin,
554 $ 1, idumm, idumm, -1, -1, mycol )
555 CALL dgamx2d( 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 dgamn2d( ictxt,
'Rowwise',
' ', 1, 1, rcmin,
574 $ 1, idumm, idumm, -1, -1, mycol )
575 CALL dgamx2d( 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 ) = dble( lwmin )
590 rwork( 1 ) = dble( 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,
'PZGESVX', -info )
655 ELSE IF( lquery )
THEN
663 CALL pzgeequ( n, n, a, ia, ja, desca, r, c, rowcnd, colcnd,
665 IF( infequ.EQ.0 )
THEN
669 CALL pzlaqge( 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 pdcopy( n, c, 1, ja, cdesc, cdesc( lld_ ), rwork, ib, jb,
704 IF( mycol.EQ.ibcol )
THEN
705 CALL dgebs2d( ictxt,
'Rowwise',
' ', np, 1, rwork( iib ),
708 CALL dgebr2d( 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 pzlacpy(
'Full', n, n, a, ia, ja, desca, af, iaf, jaf,
725 CALL pzgetrf( n, n, af, iaf, jaf, descaf, ipiv, info )
743 anorm = pzlange( norm, n, n, a, ia, ja, desca, rwork )
747 CALL pzgecon( norm, n, af, iaf, jaf, descaf, anorm, rcond, work,
748 $ lwork, rwork, lrwork, info )
752 IF( rcond.LT.pdlamch( ictxt,
'Epsilon' ) )
THEN
759 CALL pzlacpy(
'Full', n, nrhs, b, ib, jb, descb, x, ix, jx,
761 CALL pzgetrs( trans, n, nrhs, af, iaf, jaf, descaf, ipiv, x, ix,
767 CALL pzgerfs( 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 pdcopy( n, c, 1, ja, cdesc, cdesc( lld_ ), rwork, ix,
792 IF( mycol.EQ.ibcol )
THEN
793 CALL dgebs2d( ictxt,
'Rowwise',
' ', np, 1,
794 $ rwork( iix ), descx( lld_ ) )
796 CALL dgebr2d( 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 ) = dble( lwmin )
824 rwork( 1 ) = dble( lrwmin )