1 SUBROUTINE pzporfs( 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*16 A( * ), AF( * ), B( * ), WORK( * ), X( * )
19 DOUBLE PRECISION 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 DOUBLE PRECISION ZERO, RONE, TWO, THREE
267 parameter( zero = 0.0d+0, rone = 1.0d+0, two = 2.0d+0,
270 PARAMETER ( ONE = ( 1.0d+0, 0.0d+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 DOUBLE PRECISION EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
285 INTEGER DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
289 INTEGER ICEIL, INDXG2P, NUMROC
290 DOUBLE PRECISION PDLAMCH
291 EXTERNAL iceil, indxg2p, lsame, numroc, pdlamch
300 INTRINSIC abs, dble, dcmplx, dimag, ichar,
max,
min, mod
303 DOUBLE PRECISION CABS1
306 cabs1( zdum ) = abs( dble( zdum ) ) + abs( dimag( zdum ) )
312 ictxt = desca( ctxt_ )
313 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
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 ) = dcmplx( dble( lwmin ) )
354 rwork( 1 ) = dble( 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,
'PZPORFS', -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 = pdlamch( ictxt,
'Epsilon' )
472 safmin = pdlamch( ictxt,
'Safe minimum' )
475 jn =
min( iceil( jb, descb( nb_ ) ) * descb( nb_ ), jb+nrhs-1 )
480 DO 100 k = 0, jbrhs-1
490 CALL pzcopy( n, b, ib, jb+k, descb, 1, work( ipr ), iw, jw,
492 CALL pzhemv( 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 pzahemv( 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 dgamx2d( 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 pzpotrs( uplo, n, 1, af, iaf, jaf, descaf,
547 $ work( ipr ), iw, jw, descw, info )
548 CALL pzaxpy( 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 zgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
600 CALL zgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
601 $ descw( lld_ ), myrow, ixbcol )
603 descw( csrc_ ) = mycol
604 CALL pzlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
605 $ iw, jw, descw, est, kase )
606 descw( csrc_ ) = ixbcol
613 CALL pzpotrs( uplo, n, 1, af, iaf, jaf, descaf,
614 $ work( ipr ), iw, jw, descw, info )
616 IF( mycol.EQ.ixbcol )
THEN
618 DO 70 ii = iiw-1, iiw+np-2
619 work( ipr+ii ) = rwork( ipb+ii )*work( ipr+ii )
627 IF( mycol.EQ.ixbcol )
THEN
629 DO 80 ii = iiw-1, iiw+np-2
630 work( ipr+ii ) = rwork( ipb+ii )*work( ipr+ii )
635 CALL pzpotrs( uplo, n, 1, af, iaf, jaf, descaf,
636 $ work( ipr ), iw, jw, descw, info )
644 IF( mycol.EQ.ixbcol )
THEN
646 DO 90 ii = iixb, iixb+np-1
647 lstres =
max( lstres, cabs1( x( ioffxb+ii ) ) )
650 CALL dgamx2d( 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 pzcopy( n, b, ib, j+k, descb, 1, work( ipr ), iw, jw,
683 CALL pzhemv( uplo, n, -one, a, ia, ja, desca, x, ix, j+k,
684 $ descx, 1, one, work( ipr ), iw, jw, descw, 1 )
697 IF( mycol.EQ.icurcol )
THEN
699 DO 120 ii = iixb, iixb+np-1
700 rwork( iiw+ii-iixb ) = cabs1( b( ii+ioffxb ) )
705 CALL pzahemv( uplo, n, rone, a, ia, ja, desca, x, ix, j+k,
706 $ descx, 1, rone, rwork( ipb ), iw, jw, descw,
710 IF( mycol.EQ.icurcol )
THEN
712 DO 130 ii = iiw-1, iiw+np-2
713 IF( rwork( ipb+ii ).GT.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 dgamx2d( ictxt,
'All',
' ', 1, 1, s, 1, idum, idum, 1,
726 IF( mycol.EQ.icurcol )
736 IF( s.GT.eps .AND. two*s.LE.lstres .AND.
737 $ count.LE.itmax )
THEN
741 CALL pzpotrs( uplo, n, 1, af, iaf, jaf, descaf,
742 $ work( ipr ), iw, jw, descw, info )
743 CALL pzaxpy( n, one, work( ipr ), iw, jw, descw, 1, x,
744 $ ix, j+k, descx, 1 )
774 IF( mycol.EQ.icurcol )
THEN
776 DO 140 ii = iiw-1, iiw+np-2
777 IF( rwork( ipb+ii ).GT.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 IF( mycol.EQ.icurcol )
THEN
791 CALL zgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
794 CALL zgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
795 $ descw( lld_ ), myrow, icurcol )
797 descw( csrc_ ) = mycol
798 CALL pzlacon( n, work( ipv ), iw, jw, descw, work( ipr ),
799 $ iw, jw, descw, est, kase )
800 descw( csrc_ ) = icurcol
807 CALL pzpotrs( uplo, n, 1, af, iaf, jaf, descaf,
808 $ work( ipr ), iw, jw, descw, info )
810 IF( mycol.EQ.icurcol )
THEN
812 DO 160 ii = iiw-1, iiw+np-2
813 work( ipr+ii ) = rwork( ipb+ii )*
822 IF( mycol.EQ.icurcol )
THEN
824 DO 170 ii = iiw-1, iiw+np-2
825 work( ipr+ii ) = rwork( ipb+ii )*
831 CALL pzpotrs( uplo, n, 1, af, iaf, jaf, descaf,
832 $ work( ipr ), iw, jw, descw, info )
840 IF( mycol.EQ.icurcol )
THEN
842 DO 180 ii = iixb, iixb+np-1
843 lstres =
max( lstres, cabs1( x( ioffxb+ii ) ) )
846 CALL dgamx2d( 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 ) = dcmplx( dble( lwmin ) )
864 rwork( 1 ) = dble( lrwmin )