1 SUBROUTINE pctrrfs( UPLO, TRANS, DIAG, N, NRHS, A, IA, JA, DESCA,
2 $ B, IB, JB, DESCB, X, IX, JX, DESCX, FERR,
3 $ BERR, WORK, LWORK, RWORK, LRWORK, INFO )
11 CHARACTER DIAG, TRANS, UPLO
12 INTEGER INFO, IA, IB, IX, JA, JB, JX, LRWORK, LWORK,
16 INTEGER DESCA( * ), DESCB( * ), DESCX( * )
17 REAL BERR( * ), FERR( * ), RWORK( * )
18 COMPLEX A( * ), B( * ), WORK( * ), X( * )
246 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
247 $ LLD_, MB_, M_, NB_, N_, RSRC_
248 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
249 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
250 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
252 PARAMETER ( ZERO = 0.0e+0, rone = 1.0e+0 )
254 parameter( one = ( 1.0e+0, 0.0e+0 ) )
257 LOGICAL LQUERY, NOTRAN, NOUNIT, UPPER
258 CHARACTER TRANSN, TRANST
259 INTEGER IAROW, IXBCOL, IXBROW, IXCOL, IXROW, ICOFFA,
260 $ icoffb, icoffx, ictxt, icurcol, idum, ii, iixb,
261 $ iiw, ioffxb, ipb, ipr, ipv, iroffa, iroffb,
262 $ iroffx, iw, j, jbrhs, jj, jjfbe, jjxb, jn, jw,
263 $ k, kase, ldxb, lrwmin, lwmin, mycol, myrhs,
264 $ myrow, np, np0, npcol, npmod, nprow, nz
265 REAL EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
269 INTEGER DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
273 INTEGER ICEIL, INDXG2P, NUMROC
275 EXTERNAL iceil, indxg2p, lsame, numroc, pslamch
278 EXTERNAL blacs_gridinfo, cgebr2d, cgebs2d,
chk1mat,
284 INTRINSIC abs, aimag,
cmplx, ichar,
max,
min, mod, real
290 cabs1( zdum ) = abs( real( zdum ) ) + abs( aimag( zdum ) )
296 ictxt = desca( ctxt_ )
297 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
302 IF( nprow.EQ.-1 )
THEN
303 info = -( 900+ctxt_ )
305 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 9, info )
306 CALL chk1mat( n, 4, nrhs, 5, ib, jb, descb, 13, info )
307 CALL chk1mat( n, 4, nrhs, 5, ix, jx, descx, 17, info )
309 upper = lsame( uplo,
'U' )
310 notran = lsame( trans,
'N' )
311 nounit = lsame( diag,
'N' )
312 iroffa = mod( ia-1, desca( mb_ ) )
313 icoffa = mod( ja-1, desca( nb_ ) )
314 iroffb = mod( ib-1, descb( mb_ ) )
315 icoffb = mod( jb-1, descb( nb_ ) )
316 iroffx = mod( ix-1, descx( mb_ ) )
317 icoffx = mod( jx-1, descx( nb_ ) )
318 iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
320 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol,
321 $ iixb, jjxb, ixbrow, ixbcol )
322 ixrow = indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
324 ixcol = indxg2p( jx, descx( nb_ ), mycol, descx( csrc_ ),
326 npmod = numroc( n+iroffa, desca( mb_ ), myrow, iarow,
329 work( 1 ) = real( lwmin )
331 rwork( 1 ) = real( lrwmin )
332 lquery = ( lwork.EQ.-1 .OR. lrwork.EQ.-1 )
334 IF( .NOT.upper .AND. .NOT.lsame( uplo,
'L' ) )
THEN
336 ELSE IF( .NOT.notran .AND. .NOT.lsame( trans,
'T' ) .AND.
337 $ .NOT.lsame( trans,
'C' ) )
THEN
339 ELSE IF( .NOT.nounit .AND. .NOT.lsame( diag,
'U' ) )
THEN
341 ELSE IF( n.LT.0 )
THEN
343 ELSE IF( nrhs.LT.0 )
THEN
345 ELSE IF( iroffa.NE.0 )
THEN
347 ELSE IF( icoffa.NE.0 )
THEN
349 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
351 ELSE IF( iroffa.NE.iroffb .OR. iarow.NE.ixbrow )
THEN
353 ELSE IF( desca( mb_ ).NE.descb( mb_ ) )
THEN
355 ELSE IF( ictxt.NE.descb( ctxt_ ) )
THEN
356 info = -( 1300+ctxt_ )
357 ELSE IF( iroffx.NE.0 .OR. ixbrow.NE.ixrow )
THEN
359 ELSE IF( icoffb.NE.icoffx .OR. ixbcol.NE.ixcol )
THEN
361 ELSE IF( descb( mb_ ).NE.descx( mb_ ) )
THEN
363 ELSE IF( descb( nb_ ).NE.descx( nb_ ) )
THEN
365 ELSE IF( ictxt.NE.descx( ctxt_ ) )
THEN
366 info = -( 1700+ctxt_ )
367 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
369 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery )
THEN
375 idum1( 1 ) = ichar(
'U' )
377 idum1( 1 ) = ichar(
'L' )
381 idum1( 2 ) = ichar(
'N' )
382 ELSE IF( lsame( trans,
'T' ) )
THEN
383 idum1( 2 ) = ichar(
'T' )
385 idum1( 2 ) = ichar(
'C' )
389 idum1( 3 ) = ichar(
'N' )
391 idum1( 3 ) = ichar(
'U' )
394 IF( lwork.EQ.-1 )
THEN
400 IF( lrwork.EQ.-1 )
THEN
406 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 9, 0, idum1, idum2,
408 CALL pchk2mat( n, 4, nrhs, 5, ib, jb, descb, 13, n, 4, nrhs, 5,
409 $ ix, jx, descx, 17, 5, idum1, idum2, info )
412 CALL pxerbla( ictxt,
'PCTRRFS', -info )
414 ELSE IF( lquery )
THEN
419 myrhs = numroc( jb+nrhs-1, descb( nb_ ), mycol, descb( csrc_ ),
424 IF( n.LE.1 .OR. nrhs.EQ.0 )
THEN
425 DO 10 jj = jjfbe, myrhs
440 np0 = numroc( n+iroffb, descb( mb_ ), myrow, ixbrow, nprow )
441 CALL descset( descw, n+iroffb, 1, desca( mb_ ), 1, ixbrow, ixbcol,
442 $ ictxt,
max( 1, np0 ) )
446 IF( myrow.EQ.ixbrow )
THEN
456 ioffxb = ( jjxb-1 )*ldxb
461 eps = pslamch( ictxt,
'Epsilon' )
462 safmin = pslamch( ictxt,
'Safe minimum' )
465 jn =
min( iceil( jb, descb( nb_ ) )*descb( nb_ ), jb+nrhs-1 )
470 DO 90 k = 0, jbrhs - 1
475 CALL pccopy( n, x, ix, jx+k, descx, 1, work( ipr ), iw, jw,
477 CALL pctrmv( uplo, trans, diag, n, a, ia, ja, desca,
478 $ work( ipr ), iw, jw, descw, 1 )
479 CALL pcaxpy( n, -one, b, ib, jb+k, descb, 1, work( ipr ), iw,
491 IF( mycol.EQ.ixbcol )
THEN
493 DO 20 ii = iixb, iixb + np - 1
494 rwork( iiw+ii-iixb ) = cabs1( b( ii+ioffxb ) )
499 CALL pcatrmv( uplo, trans, diag, n, rone, a, ia, ja, desca, x,
500 $ ix, jx+k, descx, 1, rone, rwork( ipb ), iw, jw,
504 IF( mycol.EQ.ixbcol )
THEN
506 DO 30 ii = iiw - 1, iiw + np - 2
507 IF( rwork( ipb+ii ).GT.safe2 )
THEN
508 s =
max( s, cabs1( work( ipr+ii ) ) /
511 s =
max( s, ( cabs1( work( ipr+ii ) )+safe1 ) /
512 $ ( rwork( ipb+ii )+safe1 ) )
518 CALL sgamx2d( ictxt,
'All',
' ', 1, 1, s, 1, idum, idum, 1,
520 IF( mycol.EQ.ixbcol )
545 IF( mycol.EQ.ixbcol )
THEN
547 DO 40 ii = iiw - 1, iiw + np - 2
548 IF( rwork( ipb+ii ).GT.safe2 )
THEN
549 rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
550 $ nz*eps*rwork( ipb+ii )
552 rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
553 $ nz*eps*rwork( ipb+ii ) + safe1
561 IF( mycol.EQ.ixbcol )
THEN
562 CALL cgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
565 CALL cgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
566 $ descw( lld_ ), myrow, ixbcol )
568 descw( csrc_ ) = mycol
569 CALL pclacon( n, work( ipv ), iw, jw, descw, work( ipr ),
570 $ iw, jw, descw, est, kase )
571 descw( csrc_ ) = ixbcol
578 CALL pctrsv( uplo, transt, diag, n, a, ia, ja, desca,
579 $ work( ipr ), iw, jw, descw, 1 )
580 IF( mycol.EQ.ixbcol )
THEN
582 DO 60 ii = iiw - 1, iiw + np - 2
583 work( ipr+ii ) = rwork( ipb+ii )*work( ipr+ii )
591 IF( mycol.EQ.ixbcol )
THEN
593 DO 70 ii = iiw - 1, iiw + np - 2
594 work( ipr+ii ) = rwork( ipb+ii )*work( ipr+ii )
598 CALL pctrsv( uplo, transn, diag, n, a, ia, ja, desca,
599 $ work( ipr ), iw, jw, descw, 1 )
607 IF( mycol.EQ.ixbcol )
THEN
609 DO 80 ii = iixb, iixb + np - 1
610 lstres =
max( lstres, cabs1( x( ioffxb+ii ) ) )
613 CALL sgamx2d( ictxt,
'Column',
' ', 1, 1, lstres, 1, idum,
614 $ idum, 1, -1, mycol )
616 $ ferr( jjfbe ) = est / lstres
620 ioffxb = ioffxb + ldxb
626 icurcol = mod( ixbcol+1, npcol )
630 DO 180 j = jn + 1, jb + nrhs - 1, descb( nb_ )
631 jbrhs =
min( jb+nrhs-j, descb( nb_ ) )
632 descw( csrc_ ) = icurcol
634 DO 170 k = 0, jbrhs - 1
639 CALL pccopy( n, x, ix, j+k, descx, 1, work( ipr ), iw, jw,
641 CALL pctrmv( uplo, trans, diag, n, a, ia, ja, desca,
642 $ work( ipr ), iw, jw, descw, 1 )
643 CALL pcaxpy( n, -one, b, ib, j+k, descb, 1, work( ipr ),
656 IF( mycol.EQ.ixbcol )
THEN
658 DO 100 ii = iixb, iixb + np - 1
659 rwork( iiw+ii-iixb ) = cabs1( b( ii+ioffxb ) )
664 CALL pcatrmv( uplo, trans, diag, n, rone, a, ia, ja, desca,
665 $ x, ix, j+k, descx, 1, rone, rwork( ipb ), iw,
669 IF( mycol.EQ.ixbcol )
THEN
671 DO 110 ii = iiw - 1, iiw + np - 2
672 IF( rwork( ipb+ii ).GT.safe2 )
THEN
673 s =
max( s, cabs1( work( ipr+ii ) ) /
676 s =
max( s, ( cabs1( work( ipr+ii ) )+safe1 ) /
677 $ ( rwork( ipb+ii )+safe1 ) )
683 CALL sgamx2d( ictxt,
'All',
' ', 1, 1, s, 1, idum, idum, 1,
685 IF( mycol.EQ.ixbcol )
712 IF( mycol.EQ.ixbcol )
THEN
714 DO 120 ii = iiw - 1, iiw + np - 2
715 IF( rwork( ipb+ii ).GT.safe2 )
THEN
716 rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
717 $ nz*eps*rwork( ipb+ii )
719 rwork( ipb+ii ) = cabs1( work( ipr+ii ) ) +
720 $ nz*eps*rwork( ipb+ii ) + safe1
728 IF( mycol.EQ.ixbcol )
THEN
729 CALL cgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
732 CALL cgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
733 $ descw( lld_ ), myrow, ixbcol )
735 descw( csrc_ ) = mycol
736 CALL pclacon( n, work( ipv ), iw, jw, descw, work( ipr ),
737 $ iw, jw, descw, est, kase )
738 descw( csrc_ ) = ixbcol
745 CALL pctrsv( uplo, transt, diag, n, a, ia, ja, desca,
746 $ work( ipr ), iw, jw, descw, 1 )
747 IF( mycol.EQ.ixbcol )
THEN
749 DO 140 ii = iiw - 1, iiw + np - 2
750 work( ipr+ii ) = rwork( ipb+ii )*
759 IF( mycol.EQ.ixbcol )
THEN
761 DO 150 ii = iiw - 1, iiw + np - 2
762 work( ipr+ii ) = rwork( ipb+ii )*
767 CALL pctrsv( uplo, transn, diag, n, a, ia, ja, desca,
768 $ work( ipr ), iw, jw, descw, 1 )
776 IF( mycol.EQ.ixbcol )
THEN
778 DO 160 ii = iixb, iixb + np - 1
779 lstres =
max( lstres, cabs1( x( ioffxb+ii ) ) )
782 CALL sgamx2d( ictxt,
'Column',
' ', 1, 1, lstres, 1,
783 $ idum, idum, 1, -1, mycol )
785 $ ferr( jjfbe ) = est / lstres
789 ioffxb = ioffxb + ldxb
795 icurcol = mod( icurcol+1, npcol )
799 work( 1 ) =
cmplx( real( lwmin ) )
800 rwork( 1 ) = real( lrwmin )