1 SUBROUTINE pztrrfs( 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 DOUBLE PRECISION BERR( * ), FERR( * ), RWORK( * )
18 COMPLEX*16 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 )
251 DOUBLE PRECISION ZERO, RONE
252 PARAMETER ( ZERO = 0.0d+0, rone = 1.0d+0 )
254 parameter( one = ( 1.0d+0, 0.0d+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 DOUBLE PRECISION EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
269 INTEGER DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
273 INTEGER ICEIL, INDXG2P, NUMROC
274 DOUBLE PRECISION PDLAMCH
275 EXTERNAL iceil, indxg2p, lsame, numroc, pdlamch
280 $ pzaxpy, pzcopy,
pzlacon, pztrmv,
281 $ pztrsv, zgebr2d, zgebs2d
284 INTRINSIC abs, dble, dcmplx, dimag, ichar,
max,
min, mod
287 DOUBLE PRECISION CABS1
290 cabs1( zdum ) = abs( dble( zdum ) ) + abs( dimag( 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 ) = dble( lwmin )
331 rwork( 1 ) = dble( 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,
'PZTRRFS', -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 = pdlamch( ictxt,
'Epsilon' )
462 safmin = pdlamch( ictxt,
'Safe minimum' )
465 jn =
min( iceil( jb, descb( nb_ ) )*descb( nb_ ), jb+nrhs-1 )
470 DO 90 k = 0, jbrhs - 1
475 CALL pzcopy( n, x, ix, jx+k, descx, 1, work( ipr ), iw, jw,
477 CALL pztrmv( uplo, trans, diag, n, a, ia, ja, desca,
478 $ work( ipr ), iw, jw, descw, 1 )
479 CALL pzaxpy( 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 pzatrmv( 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 dgamx2d( 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 zgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
565 CALL zgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
566 $ descw( lld_ ), myrow, ixbcol )
568 descw( csrc_ ) = mycol
569 CALL pzlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
570 $ iw, jw, descw, est, kase )
571 descw( csrc_ ) = ixbcol
578 CALL pztrsv( 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 pztrsv( 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 dgamx2d( 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 pzcopy( n, x, ix, j+k, descx, 1, work( ipr ), iw, jw,
641 CALL pztrmv( uplo, trans, diag, n, a, ia, ja, desca,
642 $ work( ipr ), iw, jw, descw, 1 )
643 CALL pzaxpy( 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 pzatrmv( 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 dgamx2d( 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 zgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
732 CALL zgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
733 $ descw( lld_ ), myrow, ixbcol )
735 descw( csrc_ ) = mycol
736 CALL pzlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
737 $ iw, jw, descw, est, kase )
738 descw( csrc_ ) = ixbcol
745 CALL pztrsv( 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 pztrsv( 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 dgamx2d( 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 ) = dcmplx( dble( lwmin ) )
800 rwork( 1 ) = dble( lrwmin )