1 SUBROUTINE pcporfs( UPLO, N, NRHS, A, IA, JA, DESCA, AF, IAF, JAF,
2 $ DESCAF, B, IB, JB, DESCB, X, IX, JX, DESCX,
3 $ FERR, BERR, WORK, LWORK, RWORK, LRWORK, INFO )
12 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX,
13 $ lrwork, lwork, n, nrhs
16 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
18 COMPLEX A( * ), AF( * ), B( * ), WORK( * ), X( * )
19 REAL BERR( * ), FERR( * ), RWORK( * )
259 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
260 $ LLD_, MB_, M_, NB_, N_, RSRC_
261 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
262 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
263 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
265 PARAMETER ( ITMAX = 5 )
266 REAL ZERO, RONE, TWO,
267 parameter( zero = 0.0e+0, rone = 1.0e+0, two = 2.0e+0,
270 PARAMETER ( ONE = ( 1.0e+0, 0.0e+0 ) )
273 LOGICAL LQUERY, UPPER
274 INTEGER COUNT, IACOL, IAFCOL, IAFROW, IAROW, IXBCOL,
275 $ ixbrow, ixcol, ixrow, icoffa, icoffaf, icoffb,
276 $ icoffx, ictxt, icurcol, idum, ii, iixb, iiw,
277 $ ioffxb, ipb, ipr, ipv, iroffa, iroffaf, iroffb,
278 $ iroffx, iw, j, jbrhs, jj, jjfbe, jjxb, jn, jw,
279 $ k, kase, ldxb, lrwmin, lwmin, mycol, myrhs,
280 $ myrow, np, np0, npcol, npmod, nprow, nz
281 REAL EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
285 INTEGER DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
289 INTEGER ICEIL, INDXG2P, NUMROC
291 EXTERNAL iceil, indxg2p, lsame, numroc, pslamch
300 INTRINSIC abs, aimag,
cmplx, ichar,
max,
min, mod, real
306 cabs1( zdum ) = abs( real( zdum ) ) + abs( aimag( zdum ) )
312 ictxt = desca( ctxt_ )
318 IF( nprow.EQ.-1 )
THEN
321 CALL chk1mat( n, 2, n, 2, ia, ja, desca, 7, info )
322 CALL chk1mat( n, 2, n, 2, iaf, jaf, descaf, 11, info )
323 CALL chk1mat( n, 2, nrhs, 3, ib, jb, descb, 15, info )
324 CALL chk1mat( n, 2, nrhs, 3, ix, jx, descx, 19, info )
326 upper = lsame( uplo,
'U' )
327 iroffa = mod( ia-1, desca( mb_ ) )
328 icoffa = mod( ja-1, desca( nb_ ) )
329 iroffaf = mod( iaf-1, descaf( mb_ ) )
330 icoffaf = mod( jaf-1, descaf( nb_ ) )
331 iroffb = mod( ib-1, descb( mb_ ) )
332 icoffb = mod( jb-1, descb( nb_ ) )
333 iroffx = mod( ix-1, descx( mb_ ) )
334 icoffx = mod( jx-1, descx( nb_ ) )
335 iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
337 iafcol = indxg2p( jaf, descaf( nb_ ), mycol,
338 $ descaf( csrc_ ), npcol )
339 iafrow = indxg2p( iaf, descaf( mb_ ), myrow,
340 $ descaf( rsrc_ ), nprow )
341 iacol = indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
343 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol,
344 $ iixb, jjxb, ixbrow, ixbcol )
345 ixrow = indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
347 ixcol = indxg2p( jx, descx( nb_ ), mycol, descx( csrc_ ),
349 npmod = numroc( n+iroffa, desca( mb_ ), myrow, iarow,
353 work( 1 ) =
cmplx( real( lwmin ) )
354 rwork( 1 ) = real( lrwmin )
355 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
357 IF( .NOT.upper .AND. .NOT.lsame( uplo,
'L' ) )
THEN
359 ELSE IF( n.LT.0 )
THEN
361 ELSE IF( nrhs.LT.0 )
THEN
363 ELSE IF( iroffa.NE.0 )
THEN
365 ELSE IF( icoffa.NE.0 )
THEN
367 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
368 info = -( 700 + nb_ )
369 ELSE IF( desca( mb_ ).NE.descaf( mb_ ) )
THEN
370 info = -( 1100 + mb_ )
371 ELSE IF( iroffaf.NE.0 .OR. iarow.NE.iafrow )
THEN
373 ELSE IF( desca( nb_ ).NE.descaf( nb_ ) )
THEN
374 info = -( 1100 + nb_ )
375 ELSE IF( icoffaf.NE.0 .OR. iacol.NE.iafcol )
THEN
377 ELSE IF( ictxt.NE.descaf( ctxt_ ) )
THEN
378 info = -( 1100 + ctxt_ )
379 ELSE IF( iroffa.NE.iroffb .OR. iarow.NE.ixbrow )
THEN
381 ELSE IF( desca( mb_ ).NE.descb( mb_ ) )
THEN
382 info = -( 1500 + mb_ )
383 ELSE IF( ictxt.NE.descb( ctxt_ ) )
THEN
384 info = -( 1500 + ctxt_ )
385 ELSE IF( descb( mb_ ).NE.descx( mb_ ) )
THEN
386 info = -( 1900 + mb_ )
387 ELSE IF( iroffx.NE.0 .OR. ixbrow.NE.ixrow )
THEN
389 ELSE IF( descb( nb_ ).NE.descx( nb_ ) )
THEN
390 info = -( 1900 + nb_ )
391 ELSE IF( icoffb.NE.icoffx .OR. ixbcol.NE.ixcol )
THEN
393 ELSE IF( ictxt.NE.descx( ctxt_ ) )
THEN
394 info = -( 1900 + ctxt_ )
395 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
397 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery )
THEN
403 idum1( 1 ) = ichar(
'U' )
405 idum1( 1 ) = ichar(
'L' )
412 IF( lwork.EQ.-1 )
THEN
418 IF( lrwork.EQ.-1 )
THEN
424 CALL pchk2mat( n, 2, n, 2, ia, ja, desca, 7, n, 2, n, 2, iaf,
425 $ jaf, descaf, 11, 0, idum1, idum2, info )
426 CALL pchk2mat( n, 2, nrhs, 3, ib, jb, descb, 15, n, 2, nrhs, 3,
427 $ ix, jx, descx, 19, 5, idum1, idum2, info )
430 CALL pxerbla( ictxt,
'PCPORFS', -info )
432 ELSE IF( lquery )
THEN
437 myrhs = numroc( jb+nrhs-1, descb( nb_ ), mycol, descb( csrc_ ),
442 IF( n.LE.1 .OR. nrhs.EQ.0 )
THEN
443 DO 10 jj = jjfbe, myrhs
450 np0 = numroc( n+iroffb, descb( mb_ ), myrow, ixbrow, nprow )
451 CALL descset( descw, n+iroffb, 1, desca( mb_ ), 1, ixbrow, ixbcol,
452 $ ictxt,
max( 1, np0 ) )
456 IF( myrow.EQ.ixbrow )
THEN
466 ioffxb = ( jjxb-1 )*ldxb
471 eps = pslamch( ictxt,
'Epsilon' )
472 safmin = pslamch( ictxt,
'Safe minimum' )
475 jn =
min( iceil( jb, descb( nb_ ) ) * descb( nb_ ), jb+nrhs-1 )
480 DO 100 k = 0, jbrhs-1
490 CALL pccopy( n, b, ib, jb+k, descb, 1, work( ipr ), iw, jw,
492 CALL pchemv( uplo, n, -one, a, ia, ja, desca, x, ix, jx+k,
493 $ descx, 1, one, work( ipr ), iw, jw, descw, 1 )
505 IF( mycol.EQ.ixbcol )
THEN
507 DO 30 ii = iixb, iixb + np - 1
508 rwork( iiw+ii-iixb ) = cabs1( b( ii+ioffxb ) )
513 CALL pcahemv( uplo, n, rone, a, ia, ja, desca, x, ix, jx+k,
514 $ descx, 1, rone, rwork( ipb ), iw, jw, descw, 1 )
517 IF( mycol.EQ.ixbcol )
THEN
519 DO 40 ii = iiw-1, iiw+np-2
520 IF( rwork( ipb+ii ).GT.safe2 )
THEN
521 s =
max( s, cabs1( work( ipr+ii ) ) /
524 s =
max( s, ( cabs1( work( ipr+ii ) )+safe1 ) /
525 $ ( rwork( ipb+ii )+safe1 ) )
531 CALL sgamx2d( ictxt,
'All',
' ', 1, 1, s, 1, idum, idum, 1,
533 IF( mycol.EQ.ixbcol )
542 IF( s.GT.eps .AND. two*s.LE.lstres .AND. count.LE.itmax )
THEN
546 CALL pcpotrs( uplo, n, 1, af, iaf, jaf, descaf,
547 $ work( ipr ), iw, jw, descw, info )
548 CALL pcaxpy( n, one, work( ipr ), iw, jw, descw, 1, x, ix,
580 IF( mycol.EQ.ixbcol )
THEN
582 DO 50 ii = iiw-1, iiw+np-2
583 IF( rwork( ipb+ii ).GT.safe2 )
THEN
584 rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
585 $ nz*eps*rwork( ipb+ii )
587 rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
588 $ nz*eps*rwork( ipb+ii ) + safe1
596 IF( mycol.EQ.ixbcol )
THEN
597 CALL cgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
600 CALL cgebr2d( ictxt,
'Rowwise', '
', NP, 1, WORK( IPR ),
601 $ DESCW( LLD_ ), MYROW, IXBCOL )
603 DESCW( CSRC_ ) = MYCOL
604 CALL PCLACON( N, WORK( IPV ), IW, JW, DESCW, WORK( IPR ),
605 $ IW, JW, DESCW, EST, KASE )
606 DESCW( CSRC_ ) = IXBCOL
613 CALL PCPOTRS( UPLO, N, 1, AF, IAF, JAF, DESCAF,
614 $ WORK( IPR ), IW, JW, DESCW, INFO )
616.EQ.
IF( MYCOLIXBCOL ) THEN
618 DO 70 II = IIW-1, IIW+NP-2
619 WORK( IPR+II ) = RWORK( IPB+II )*WORK( IPR+II )
627.EQ.
IF( MYCOLIXBCOL ) THEN
629 DO 80 II = IIW-1, IIW+NP-2
630 WORK( IPR+II ) = RWORK( IPB+II )*WORK( IPR+II )
635 CALL PCPOTRS( UPLO, N, 1, AF, IAF, JAF, DESCAF,
636 $ WORK( IPR ), IW, JW, DESCW, INFO )
644.EQ.
IF( MYCOLIXBCOL ) THEN
646 DO 90 II = IIXB, IIXB+NP-1
647 LSTRES = MAX( LSTRES, CABS1( X( IOFFXB+II ) ) )
650 CALL SGAMX2D( ICTXT, 'column
', ' ', 1, 1, LSTRES, 1, IDUM,
651 $ IDUM, 1, -1, MYCOL )
653 $ FERR( JJFBE ) = EST / LSTRES
657 IOFFXB = IOFFXB + LDXB
663 ICURCOL = MOD( IXBCOL+1, NPCOL )
667 DO 200 J = JN+1, JB+NRHS-1, DESCB( NB_ )
668 JBRHS = MIN( JB+NRHS-J, DESCB( NB_ ) )
669 DESCW( CSRC_ ) = ICURCOL
671 DO 190 K = 0, JBRHS-1
681 CALL PCCOPY( N, B, IB, J+K, DESCB, 1, WORK( IPR ), IW, JW,
683 CALL PCHEMV( UPLO, N, -ONE, A, IA, JA, DESCA, X, IX, J+K,
684 $ DESCX, 1, ONE, WORK( IPR ), IW, JW, DESCW, 1 )
697.EQ.
IF( MYCOLICURCOL ) THEN
699 DO 120 II = IIXB, IIXB+NP-1
700 RWORK( IIW+II-IIXB ) = CABS1( B( II+IOFFXB ) )
705 CALL PCAHEMV( UPLO, N, RONE, A, IA, JA, DESCA, X, IX, J+K,
706 $ DESCX, 1, RONE, RWORK( IPB ), IW, JW, DESCW,
710.EQ.
IF( MYCOLICURCOL ) THEN
712 DO 130 II = IIW-1, IIW+NP-2
713.GT.
IF( RWORK( IPB+II )SAFE2 ) THEN
714 S = MAX( S, CABS1( WORK( IPR+II ) ) /
717 S = MAX( S, ( CABS1( WORK( IPR+II ) )+SAFE1 ) /
718 $ ( RWORK( IPB+II )+SAFE1 ) )
724 CALL SGAMX2D( ICTXT, 'all
', ' ', 1, 1, S, 1, IDUM, IDUM, 1,
726.EQ.
IF( MYCOLICURCOL )
736.GT..AND..LE..AND.
IF( SEPS TWO*SLSTRES
737.LE.
$ COUNTITMAX ) THEN
741 CALL PCPOTRS( UPLO, N, 1, AF, IAF, JAF, DESCAF,
742 $ WORK( IPR ), IW, JW, DESCW, INFO )
743 CALL PCAXPY( N, ONE, WORK( IPR ), IW, JW, DESCW, 1, X,
744 $ IX, J+K, DESCX, 1 )
774.EQ.
IF( MYCOLICURCOL ) THEN
776 DO 140 II = IIW-1, IIW+NP-2
777.GT.
IF( RWORK( IPB+II )SAFE2 ) THEN
778 RWORK( IPB+II ) = CABS1( WORK( IPR+II ) ) +
779 $ NZ*EPS*RWORK( IPB+II )
781 RWORK( IPB+II ) = CABS1( WORK( IPR+II ) ) +
782 $ NZ*EPS*RWORK( IPB+II ) + SAFE1
790.EQ.
IF( MYCOLICURCOL ) THEN
791 CALL CGEBS2D( ICTXT, 'rowwise
', ' ', NP, 1, WORK( IPR ),
794 CALL CGEBR2D( ICTXT, 'rowwise
', ' ', NP, 1, WORK( IPR ),
795 $ DESCW( LLD_ ), MYROW, ICURCOL )
797 DESCW( CSRC_ ) = MYCOL
798 CALL PCLACON( N, WORK( IPV ), IW, JW, DESCW, WORK( IPR ),
799 $ IW, JW, DESCW, EST, KASE )
800 DESCW( CSRC_ ) = ICURCOL
807 CALL PCPOTRS( UPLO, N, 1, AF, IAF, JAF, DESCAF,
808 $ WORK( IPR ), IW, JW, DESCW, INFO )
810.EQ.
IF( MYCOLICURCOL ) THEN
812 DO 160 II = IIW-1, IIW+NP-2
813 WORK( IPR+II ) = RWORK( IPB+II )*
822.EQ.
IF( MYCOLICURCOL ) THEN
824 DO 170 II = IIW-1, IIW+NP-2
825 WORK( IPR+II ) = RWORK( IPB+II )*
831 CALL PCPOTRS( UPLO, N, 1, AF, IAF, JAF, DESCAF,
832 $ WORK( IPR ), IW, JW, DESCW, INFO )
840.EQ.
IF( MYCOLICURCOL ) THEN
842 DO 180 II = IIXB, IIXB+NP-1
843 LSTRES = MAX( LSTRES, CABS1( X( IOFFXB+II ) ) )
846 CALL SGAMX2D( ICTXT, 'column
', ' ', 1, 1, LSTRES, 1,
847 $ IDUM, IDUM, 1, -1, MYCOL )
849 $ FERR( JJFBE ) = EST / LSTRES
853 IOFFXB = IOFFXB + LDXB
859 ICURCOL = MOD( ICURCOL+1, NPCOL )
863 WORK( 1 ) = CMPLX( REAL( LWMIN ) )
864 RWORK( 1 ) = REAL( LRWMIN )