1 SUBROUTINE psporfs( 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, IWORK, LIWORK, INFO )
12 INTEGER IA, IAF, IB, INFO, IX, JA, JAF, JB, JX,
13 $ liwork, lwork, n, nrhs
16 INTEGER DESCA( * ), DESCAF( * ), DESCB( * ),
17 $ DESCX( * ), IWORK( * )
18 REAL A( * ), AF( * ), B( * ),
19 $ BERR( * ), FERR( * ), WORK( * ), X( * )
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 )
267 parameter( zero = 0.0e+0, one = 1.0e+0 )
269 parameter( two = 2.0e+0, three = 3.0e+0 )
272 LOGICAL LQUERY, UPPER
273 INTEGER COUNT, IACOL, IAFCOL, IAFROW, IAROW, IXBCOL,
274 $ ixbrow, ixcol, ixrow, icoffa, icoffaf, icoffb,
275 $ icoffx, ictxt, icurcol, idum, ii, iixb, iiw,
276 $ ioffxb, ipb, ipr, ipv, iroffa, iroffaf, iroffb,
277 $ iroffx, iw, j, jbrhs, jj, jjfbe, jjxb, jn, jw,
278 $ k, kase, ldxb, liwmin, lwmin, mycol, myrhs,
279 $ myrow, np, np0, npcol, npmod, nprow, nz
280 REAL EPS, EST, LSTRES, S, SAFE1, SAFE2, SAFMIN
283 INTEGER DESCW( DLEN_ ), IDUM1( 5 ), IDUM2( 5 )
287 INTEGER ICEIL, INDXG2P, NUMROC
289 EXTERNAL iceil, indxg2p, lsame, numroc, pslamch
293 $
pchk2mat, psasymv, psaxpy, pscopy,
295 $ sgamx2d, sgebr2d, sgebs2d
298 INTRINSIC abs, ichar,
max,
min, mod, real
304 ictxt = desca( ctxt_ )
305 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
310 IF( nprow.EQ.-1 )
THEN
313 CALL chk1mat( n, 2, n, 2, ia, ja, desca, 7, info )
314 CALL chk1mat( n, 2, n, 2, iaf, jaf, descaf, 11, info )
315 CALL chk1mat( n, 2, nrhs, 3, ib, jb, descb, 15, info )
316 CALL chk1mat( n, 2, nrhs, 3, ix, jx, descx, 19, info )
318 upper = lsame( uplo,
'U' )
319 iroffa = mod( ia-1, desca( mb_ ) )
320 icoffa = mod( ja-1, desca( nb_ ) )
321 iroffaf = mod( iaf-1, descaf( mb_ ) )
322 icoffaf = mod( jaf-1, descaf( nb_ ) )
323 iroffb = mod( ib-1, descb( mb_ ) )
324 icoffb = mod( jb-1, descb( nb_ ) )
325 iroffx = mod( ix-1, descx( mb_ ) )
326 icoffx = mod( jx-1, descx( nb_ ) )
327 iarow = indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
329 iafcol = indxg2p( jaf, descaf( nb_ ), mycol,
330 $ descaf( csrc_ ), npcol )
331 iafrow = indxg2p( iaf, descaf( mb_ ), myrow,
332 $ descaf( rsrc_ ), nprow )
333 iacol = indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
335 CALL infog2l( ib, jb, descb, nprow, npcol, myrow, mycol,
336 $ iixb, jjxb, ixbrow, ixbcol )
337 ixrow = indxg2p( ix, descx( mb_ ), myrow, descx( rsrc_ ),
339 ixcol = indxg2p( jx, descx( nb_ ), mycol, descx( csrc_ ),
341 npmod = numroc( n+iroffa, desca( mb_ ), myrow, iarow,
345 work( 1 ) = real( lwmin )
347 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
349 IF( .NOT.upper .AND. .NOT.lsame( uplo,
'L' ) )
THEN
351 ELSE IF( n.LT.0 )
THEN
353 ELSE IF( nrhs.LT.0 )
THEN
355 ELSE IF( iroffa.NE.0 )
THEN
357 ELSE IF( icoffa.NE.0 )
THEN
359 ELSE IF( desca( mb_ ).NE.desca( nb_ ) )
THEN
360 info = -( 700 + nb_ )
361 ELSE IF( desca( mb_ ).NE.descaf( mb_ ) )
THEN
362 info = -( 1100 + mb_ )
363 ELSE IF( iroffaf.NE.0 .OR. iarow.NE.iafrow )
THEN
365 ELSE IF( desca( nb_ ).NE.descaf( nb_ ) )
THEN
366 info = -( 1100 + nb_ )
367 ELSE IF( icoffaf.NE.0 .OR. iacol.NE.iafcol )
THEN
369 ELSE IF( ictxt.NE.descaf( ctxt_ ) )
THEN
370 info = -( 1100 + ctxt_ )
371 ELSE IF( iroffa.NE.iroffb .OR. iarow.NE.ixbrow )
THEN
373 ELSE IF( desca( mb_ ).NE.descb( mb_ ) )
THEN
374 info = -( 1500 + mb_ )
375 ELSE IF( ictxt.NE.descb( ctxt_ ) )
THEN
376 info = -( 1500 + ctxt_ )
377 ELSE IF( descb( mb_ ).NE.descx( mb_ ) )
THEN
378 info = -( 1900 + mb_ )
379 ELSE IF( iroffx.NE.0 .OR. ixbrow.NE.ixrow )
THEN
381 ELSE IF( descb( nb_ ).NE.descx( nb_ ) )
THEN
382 info = -( 1900 + nb_ )
383 ELSE IF( icoffb.NE.icoffx .OR. ixbcol.NE.ixcol )
THEN
385 ELSE IF( ictxt.NE.descx( ctxt_ ) )
THEN
386 info = -( 1900 + ctxt_ )
387 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery )
THEN
389 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery )
THEN
395 idum1( 1 ) = ichar(
'U' )
397 idum1( 1 ) = ichar(
'L' )
404 IF( lwork.EQ.-1 )
THEN
410 IF( liwork.EQ.-1 )
THEN
416 CALL pchk2mat( n, 2, n, 2, ia, ja, desca, 7, n, 2, n, 2, iaf,
417 $ jaf, descaf, 11, 0, idum1, idum2, info )
418 CALL pchk2mat( n, 2, nrhs, 3, ib, jb, descb, 15, n, 2, nrhs, 3,
419 $ ix, jx, descx, 19, 5, idum1, idum2, info )
422 CALL pxerbla( ictxt,
'PSPORFS', -info )
424 ELSE IF( lquery )
THEN
429 myrhs = numroc( jb+nrhs-1, descb( nb_ ), mycol, descb( csrc_ ),
434 IF( n.LE.1 .OR. nrhs.EQ.0 )
THEN
435 DO 10 jj = jjfbe, myrhs
442 np0 = numroc( n+iroffb, descb( mb_ ), myrow, ixbrow, nprow )
443 CALL descset( descw, n+iroffb, 1, desca( mb_ ), 1, ixbrow, ixbcol,
444 $ ictxt,
max( 1, np0 ) )
448 IF( myrow.EQ.ixbrow )
THEN
458 ioffxb = ( jjxb-1 )*ldxb
463 eps = pslamch( ictxt,
'Epsilon' )
464 safmin = pslamch( ictxt,
'Safe minimum' )
467 jn =
min( iceil( jb, descb( nb_ ) ) * descb( nb_ ), jb+nrhs-1 )
472 DO 100 k = 0, jbrhs-1
482 CALL pscopy( n, b, ib, jb+k, descb, 1, work( ipr ), iw, jw,
484 CALL pssymv( uplo, n, -one, a, ia, ja, desca, x, ix, jx+k,
485 $ descx, 1, one, work( ipr ), iw, jw, descw, 1 )
497 IF( mycol.EQ.ixbcol )
THEN
499 DO 30 ii = iixb, iixb + np - 1
500 work( iiw+ii-iixb ) = abs( b( ii+ioffxb ) )
505 CALL psasymv( uplo, n, one, a, ia, ja, desca, x, ix, jx+k,
506 $ descx, 1, one, work( ipb ), iw, jw, descw, 1 )
509 IF( mycol.EQ.ixbcol )
THEN
511 DO 40 ii = iiw-1, iiw+np-2
512 IF( work( ipb+ii ).GT.safe2 )
THEN
513 s =
max( s, abs( work( ipr+ii ) ) /
516 s =
max( s, ( abs( work( ipr+ii ) )+safe1 ) /
517 $ ( work( ipb+ii )+safe1 ) )
523 CALL sgamx2d( ictxt,
'All',
' ', 1, 1, s, 1, idum, idum, 1,
525 IF( mycol.EQ.ixbcol )
534 IF( s.GT.eps .AND. two*s.LE.lstres .AND. count.LE.itmax )
THEN
538 CALL pspotrs( uplo, n, 1, af, iaf, jaf, descaf,
539 $ work( ipr ), iw, jw, descw, info )
540 CALL psaxpy( n, one, work( ipr ), iw, jw, descw, 1, x, ix,
572 IF( mycol.EQ.ixbcol )
THEN
574 DO 50 ii = iiw-1, iiw+np-2
575 IF( work( ipb+ii ).GT.safe2 )
THEN
576 work( ipb+ii ) = abs( work( ipr+ii ) ) +
577 $ nz*eps*work( ipb+ii )
579 work( ipb+ii ) = abs( work( ipr+ii ) ) +
580 $ nz*eps*work( ipb+ii ) + safe1
588 IF( mycol.EQ.ixbcol )
THEN
589 CALL sgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
592 CALL sgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
593 $ descw( lld_ ), myrow, ixbcol )
595 descw( csrc_ ) = mycol
596 CALL pslacon( n, work( ipv ), iw, jw, descw, work( ipr ),
597 $ iw, jw, descw, iwork, est, kase )
598 descw( csrc_ ) = ixbcol
605 CALL pspotrs( uplo, n, 1, af, iaf, jaf, descaf,
606 $ work( ipr ), iw, jw, descw, info )
608 IF( mycol.EQ.ixbcol )
THEN
610 DO 70 ii = iiw-1, iiw+np-2
611 work( ipr+ii ) = work( ipb+ii )*work( ipr+ii )
619 IF( mycol.EQ.ixbcol )
THEN
621 DO 80 ii = iiw-1, iiw+np-2
622 work( ipr+ii ) = work( ipb+ii )*work( ipr+ii )
627 CALL pspotrs( uplo, n, 1, af, iaf, jaf, descaf,
628 $ work( ipr ), iw, jw, descw, info )
636 IF( mycol.EQ.ixbcol )
THEN
638 DO 90 ii = iixb, iixb+np-1
639 lstres =
max( lstres, abs( x( ioffxb+ii ) ) )
642 CALL sgamx2d( ictxt,
'Column',
' ', 1, 1, lstres, 1, idum,
643 $ idum, 1, -1, mycol )
645 $ ferr( jjfbe ) = est / lstres
649 ioffxb = ioffxb + ldxb
655 icurcol = mod( ixbcol+1, npcol )
659 DO 200 j = jn+1, jb+nrhs-1, descb( nb_ )
660 jbrhs =
min( jb+nrhs-j, descb( nb_ ) )
661 descw( csrc_ ) = icurcol
663 DO 190 k = 0, jbrhs-1
673 CALL pscopy( n, b, ib, j+k, descb, 1, work( ipr ), iw, jw,
675 CALL pssymv( uplo, n, -one, a, ia, ja, desca, x, ix, j+k,
676 $ descx, 1, one, work( ipr ), iw, jw, descw, 1 )
689 IF( mycol.EQ.icurcol )
THEN
691 DO 120 ii = iixb, iixb+np-1
692 work( iiw+ii-iixb ) = abs( b( ii+ioffxb ) )
697 CALL psasymv( uplo, n, one, a, ia, ja, desca, x, ix, j+k,
698 $ descx, 1, one, work( ipb ), iw, jw, descw, 1 )
701 IF( mycol.EQ.icurcol )
THEN
703 DO 130 ii = iiw-1, iiw+np-2
704 IF( work( ipb+ii ).GT.safe2 )
THEN
705 s =
max( s, abs( work( ipr+ii ) ) /
708 s =
max( s, ( abs( work( ipr+ii ) )+safe1 ) /
709 $ ( work( ipb+ii )+safe1 ) )
715 CALL sgamx2d( ictxt,
'All',
' ', 1, 1, s, 1, idum, idum, 1,
717 IF( mycol.EQ.icurcol )
727 IF( s.GT.eps .AND. two*s.LE.lstres .AND.
728 $ count.LE.itmax )
THEN
732 CALL pspotrs( uplo, n, 1, af, iaf, jaf, descaf,
733 $ work( ipr ), iw, jw, descw, info )
734 CALL psaxpy( n, one, work( ipr ), iw, jw, descw, 1, x,
735 $ ix, j+k, descx, 1 )
765 IF( mycol.EQ.icurcol )
THEN
767 DO 140 ii = iiw-1, iiw+np-2
768 IF( work( ipb+ii ).GT.safe2 )
THEN
769 work( ipb+ii ) = abs( work( ipr+ii ) ) +
770 $ nz*eps*work( ipb+ii )
772 work( ipb+ii ) = abs( work( ipr+ii ) ) +
773 $ nz*eps*work( ipb+ii ) + safe1
781 IF( mycol.EQ.icurcol )
THEN
782 CALL sgebs2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
785 CALL sgebr2d( ictxt,
'Rowwise',
' ', np, 1, work( ipr ),
786 $ descw( lld_ ), myrow, icurcol )
788 descw( csrc_ ) = mycol
789 CALL pslacon( n, work( ipv ), iw, jw, descw, work( ipr ),
790 $ iw, jw, descw, iwork, est, kase )
791 descw( csrc_ ) = icurcol
798 CALL pspotrs( uplo, n, 1, af, iaf, jaf, descaf,
799 $ work( ipr ), iw, jw, descw, info )
801 IF( mycol.EQ.icurcol )
THEN
803 DO 160 ii = iiw-1, iiw+np-2
804 work( ipr+ii ) = work( ipb+ii )*
813 IF( mycol.EQ.icurcol )
THEN
815 DO 170 ii = iiw-1, iiw+np-2
816 work( ipr+ii ) = work( ipb+ii )*
822 CALL pspotrs( uplo, n, 1, af, iaf, jaf, descaf,
823 $ work( ipr ), iw, jw, descw, info )
831 IF( mycol.EQ.icurcol )
THEN
833 DO 180 ii = iixb, iixb+np-1
834 lstres =
max( lstres, abs( x( ioffxb+ii ) ) )
837 CALL sgamx2d( ictxt,
'Column',
' ', 1, 1, lstres, 1,
838 $ idum, idum, 1, -1, mycol )
840 $ ferr( jjfbe ) = est / lstres
844 ioffxb = ioffxb + ldxb
850 icurcol = mod( icurcol+1, npcol )
854 work( 1 ) = real( lwmin )