1 SUBROUTINE psstebz( ICTXT, RANGE, ORDER, N, VL, VU, IL, IU,
2 $ ABSTOL, D, E, M, NSPLIT, W, IBLOCK, ISPLIT,
3 $ WORK, LWORK, IWORK, LIWORK, INFO )
11 CHARACTER ORDER, RANGE
12 INTEGER ICTXT, IL, INFO, IU, LIWORK, LWORK, M, N,
17 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
18 REAL D( * ), E( * ), W( * ), WORK( * )
209 INTRINSIC abs, ichar,
max,
min, mod, real
215 EXTERNAL lsame, blacs_pnum, pslamch
218 EXTERNAL blacs_freebuff, blacs_get, blacs_gridexit,
219 $ blacs_gridinfo, blacs_gridmap,
globchk,
220 $ igebr2d, igebs2d, igerv2d, igesd2d, igsum2d,
222 $ sgebr2d, sgebs2d, sgerv2d, sgesd2d,
slasrt2
225 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
226 $ MB_, NB_, RSRC_, CSRC_, LLD_
227 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
228 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
229 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
230 INTEGER BIGNUM, DESCMULT
231 PARAMETER ( BIGNUM = 10000, descmult = 100 )
232 REAL ZERO, ONE, TWO, FIVE, HALF
233 parameter( zero = 0.0e+0, one = 1.0e+0, two = 2.0e+0,
234 $ five = 5.0e+0, half = 1.0e+0 / two )
236 PARAMETER ( FUDGE = 2.0e+0, relfac = 2.0e+0 )
240 INTEGER BLKNO, FOUND, I, IBEGIN, IEFLAG, IEND, IFRST,
241 $ iinfo, ilast, iload, im, imyload, in, indriw1,
242 $ indriw2, indrw1, indrw2, inxtload, ioff,
243 $ iorder, iout, irange, irecv, irem, itmp1,
244 $ itmp2, j, jb, k, last, lextra, lreq, mycol,
245 $ myrow, nalpha, nbeta, ncmp, neigint, next, ngl,
246 $ nglob, ngu, nint, npcol, nprow, offset,
247 $ onedcontext, p, prev, rextra, rreq, self,
249 REAL ALPHA, ATOLI, BETA, BNORM, DRECV, DSEND, GL,
250 $ GU, INITVL, INITVU, LSAVE, MID, PIVMIN, RELTOL,
251 $ safemn, tmp1, tmp2, tnorm, ulp
258 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
263 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
270 IF( lsame( range,
'A' ) )
THEN
272 ELSE IF( lsame( range,
'V' ) )
THEN
274 ELSE IF( lsame( range,
'I' ) )
THEN
282 IF( lsame( order,
'B' ) )
THEN
284 ELSE IF( lsame( order,
'E' ) .OR. lsame( order,
'A' ) )
THEN
292 IF( nprow.EQ.-1 )
THEN
298 safemn = pslamch( ictxt,
'S' )
299 ulp = pslamch( ictxt,
'P' )
301 idum( 1, 1 ) = ichar( range )
303 idum( 2, 1 ) = ichar( order )
308 IF( irange.EQ.3 )
THEN
319 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
THEN
321 IF( irange.EQ.2 )
THEN
328 CALL sgebs2d( ictxt,
'ALL',
' ', 3, 1, work, 3 )
330 CALL sgebr2d( ictxt,
'ALL',
' ', 3, 1, work, 3, 0, 0 )
332 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
334 IF( irange.EQ.0 )
THEN
336 ELSE IF( iorder.EQ.0 )
THEN
338 ELSE IF( irange.EQ.2 .AND. vl.GE.vu )
THEN
340 ELSE IF( irange.EQ.3 .AND. ( il.LT.1 .OR. il.GT.
max( 1,
343 ELSE IF( irange.EQ.3 .AND. ( iu.LT.
min( n,
344 $ il ) .OR. iu.GT.n ) )
THEN
346 ELSE IF( lwork.LT.
max( 5*n, 7 ) .AND. .NOT.lquery )
THEN
348 ELSE IF( liwork.LT.
max( 4*n, 14, nprow*npcol ) .AND. .NOT.
351 ELSE IF( irange.EQ.2 .AND. ( abs( work( 2 )-vl ).GT.five*
352 $ ulp*abs( vl ) ) )
THEN
354 ELSE IF( irange.EQ.2 .AND. ( abs( work( 3 )-vu ).GT.five*
355 $ ulp*abs( vu ) ) )
THEN
357 ELSE IF( abs( work( 1 )-abstol ).GT.five*ulp*abs( abstol ) )
364 CALL globchk( ictxt, nglob, idum, 5, iwork, info )
365 IF( info.EQ.bignum )
THEN
367 ELSE IF( mod( info, descmult ).EQ.0 )
THEN
368 info = -info / descmult
373 work( 1 ) = real(
max( 5*n, 7 ) )
374 iwork( 1 ) =
max( 4*n, 14, nprow*npcol )
377 CALL pxerbla( ictxt,
'PSSTEBZ', -info )
379 ELSE IF( lwork.EQ.-1 .AND. liwork.EQ.-1 )
THEN
390 DO 20 i = 0, nprow - 1
391 DO 10 j = 0, npcol - 1
392 iwork( k ) = blacs_pnum( ictxt, i, j )
401 CALL blacs_get( ictxt, 10, onedcontext )
402 CALL blacs_gridmap( onedcontext, iwork, nprow, nprow, npcol )
403 CALL blacs_gridinfo( onedcontext, i, j, k, self )
407 IF( irange.EQ.3 .AND. il.EQ.1 .AND. iu.EQ.n )
410 next = mod( self+1, p )
411 prev = mod( p+self-1, p )
416 indrw1 =
max( 2*n, 4 )
417 indrw2 = indrw1 + 2*n
418 indriw1 =
max( 2*n, 8 )
420 work( indrw1+2*n ) = zero
426 work( indrw1+j-1 ) = d( i )
427 IF( abs( d( i+1 )*d( i ) )*ulp**2+safemn.GT.tmp1 )
THEN
430 work( indrw1+j ) = zero
432 work( indrw1+j ) = tmp1
433 pivmin =
max( pivmin, tmp1 )
436 work( indrw1+2*n-1 ) = d( n )
438 pivmin = pivmin*safemn
448 gu =
max( gu, d( i )+tmp1+tmp2 )
449 gl =
min( gl, d( i )-tmp1-tmp2 )
452 gu =
max( gu, d( n )+tmp1 )
453 gl =
min( gl, d( n )-tmp1 )
454 tnorm =
max( abs( gl ), abs( gu ) )
455 gl = gl - fudge*tnorm*ulp*n - fudge*two*pivmin
456 gu = gu + fudge*tnorm*ulp*n + fudge*pivmin
458 IF( abstol.LE.zero )
THEN
467 IF( irange.EQ.1 .OR. nsplit.EQ.1 )
THEN
468 CALL pslasnbt( ieflag )
477 IF( irange.EQ.1 )
THEN
486 ELSE IF( irange.EQ.2 )
THEN
488 IF( ieflag.EQ.0 )
THEN
489 CALL pslapdct( vl, n, work( indrw1+1 ), pivmin, ifrst )
491 CALL pslaiect( vl, n, work( indrw1+1 ), ifrst )
500 IF( ieflag.EQ.0 )
THEN
501 CALL pslapdct( vu, n, work( indrw1+1 ), pivmin, ilast )
503 CALL pslaiect( vu, n, work( indrw1+1 ), ilast )
512 iwork( 1 ) = ifrst - 1
514 ELSE IF( irange.EQ.3 )
THEN
521 CALL pslaebz( 0, n, 2, 1, atoli, reltol, pivmin,
522 $ work( indrw1+1 ), iwork( 5 ), work, iwork, nint,
523 $ lsave, ieflag, iinfo )
524 IF( iinfo.NE.0 )
THEN
529 IF( iwork( 5 ).EQ.il-1 )
THEN
530 work( 2 ) = work( 4 )
531 iwork( 2 ) = iwork( 4 )
533 work( 1 ) = work( 3 )
534 iwork( 1 ) = iwork( 3 )
536 IF( iwork( 1 ).LT.0 .OR. iwork( 1 ).GT.il-1 .OR.
537 $ iwork( 2 ).LE.
min( iu-1, iwork( 1 ) ) .OR.
538 $ iwork( 2 ).GT.n )
THEN
543 lextra = il - 1 - iwork( 1 )
544 rextra = iwork( 2 ) - iu
558 indriw2 = indriw1 + ngu - ngl
562 IF( ifrst.EQ.1 .AND. ilast.EQ.n )
573 IF( irange.NE.1 )
THEN
578 CALL igsum2d( onedcontext,
'All',
' ', 1, 1, found, 1,
594 DO 50 j = ibegin, iend - 1
596 gu =
max( gu, d( j )+tmp1+tmp2 )
597 gl =
min( gl, d( j )-tmp1-tmp2 )
601 gu =
max( gu, d( iend )+tmp1 )
602 gl =
min( gl, d( iend )-tmp1 )
603 bnorm =
max( abs( gl ), abs( gu ) )
604 gl = gl - fudge*bnorm*ulp*in - fudge*pivmin
605 gu = gu + fudge*bnorm*ulp*in + fudge*pivmin
609 IF( abstol.LE.zero )
THEN
615 IF( gl.LT.initvl )
THEN
617 IF( ieflag.EQ.0 )
THEN
618 CALL pslapdct( gl, in, work( indrw1+2*ioff+1 ),
621 CALL pslaiect( gl, in, work( indrw1+2*ioff+1 ), ngl )
626 IF( gu.GT.initvu )
THEN
628 IF( ieflag.EQ.0 )
THEN
629 CALL pslapdct( gu, in, work( indrw1+2*ioff+1 ),
632 CALL pslaiect( gu, in, work( indrw1+2*ioff+1 ), ngu )
652 irem = ncmp - iload*p
653 itmp1 = mod( self-found, p )
656 IF( itmp1.LT.irem )
THEN
661 IF( imyload.EQ.0 )
THEN
663 ELSE IF( in.EQ.1 )
THEN
664 work( indrw2+im+1 ) = work( indrw1+2*ioff+1 )
665 iwork( indriw1+im+1 ) = blkno
666 iwork( indriw2+im+1 ) = offset + 1
671 itmp2 = mod( self+1-found, p )
675 $ inxtload = inxtload + 1
676 lreq = ngl + itmp1*iload +
min( irem, itmp1 )
677 rreq = lreq + imyload
682 CALL pslaebz( 1, in, 1, 1, atoli, reltol, pivmin,
683 $ work( indrw1+2*ioff+1 ), iwork( 5 ), work,
684 $ iwork, nint, lsave, ieflag, iinfo )
690 IF( nbeta.GT.rreq+inxtload )
THEN
694 last = mod( found+
min( ngu-ngl, p )-1, p )
697 IF( self.NE.last )
THEN
698 CALL sgesd2d( onedcontext, 1, 1, dsend, 1, 0, next )
699 CALL igesd2d( onedcontext, 1, 1, nbeta, 1, 0, next )
701 IF( self.NE.mod( found, p ) )
THEN
702 CALL sgerv2d( onedcontext, 1, 1, drecv, 1, 0, prev )
703 CALL igerv2d( onedcontext, 1, 1, irecv, 1, 0, prev )
708 work( 1 ) =
max( lsave, drecv )
710 alpha =
max( alpha, work( 1 ) )
711 nalpha =
max( nalpha, irecv )
712 IF( beta-alpha.LE.
max( atoli, reltol*
max( abs( alpha ),
713 $ abs( beta ) ) ) )
THEN
714 mid = half*( alpha+beta )
715 DO 60 j = offset + nalpha + 1, offset + nbeta
716 work( indrw2+im+1 ) = mid
717 iwork( indriw1+im+1 ) = blkno
718 iwork( indriw2+im+1 ) = j
725 neigint = iwork( 2 ) - iwork( 1 )
731 CALL pslaebz( 2, in, neigint, 1, atoli, reltol, pivmin,
732 $ work( indrw1+2*ioff+1 ), iwork, work, iwork,
733 $ iout, lsave, ieflag, iinfo )
734 IF( iinfo.NE.0 )
THEN
738 mid = half*( work( 2*i-1 )+work( 2*i ) )
739 IF( i.GT.iout-iinfo )
741 DO 70 j = offset + iwork( 2*i-1 ) + 1,
742 $ offset + iwork( 2*i )
743 work( indrw2+im+1 ) = mid
744 iwork( indriw1+im+1 ) = blkno
745 iwork( indriw2+im+1 ) = j
755 CALL igsum2d( onedcontext,
'ALL',
' ', 1, 1, m, 1, -1, -1 )
760 IF( self.EQ.i-1 )
THEN
761 CALL igebs2d( onedcontext,
'ALL',
' ', 1, 1, im, 1 )
763 CALL igebs2d( onedcontext,
'ALL',
' ', im, 1,
764 $ iwork( indriw2+1 ), im )
765 CALL sgebs2d( onedcontext,
'ALL',
' ', im, 1,
766 $ work( indrw2+1 ), im )
767 CALL igebs2d( onedcontext,
'ALL',
' ', im, 1,
768 $ iwork( indriw1+1 ), im )
770 w( iwork( indriw2+j ) ) = work( indrw2+j )
771 iblock( iwork( indriw2+j ) ) = iwork( indriw1+j )
775 CALL igebr2d( onedcontext,
'ALL',
' ', 1, 1, torecv, 1, 0,
777 IF( torecv.NE.0 )
THEN
778 CALL igebr2d( onedcontext,
'ALL',
' ', torecv, 1, iwork,
780 CALL sgebr2d( onedcontext,
'ALL',
' ', torecv, 1, work,
782 CALL igebr2d( onedcontext,
'ALL',
' ', torecv, 1,
783 $ iwork( n+1 ), torecv, 0, i-1 )
785 w( iwork( j ) ) = work( j )
786 iblock( iwork( j ) ) = iwork( n+j )
791 IF( nsplit.GT.1 .AND. iorder.EQ.1 )
THEN
799 CALL slasrt2(
'I', m, w, iwork( m+1 ), iinfo )
801 iwork( i ) = iblock( i )
804 iblock( i ) = iwork( iwork( m+i ) )
807 IF( irange.EQ.3 .AND. ( lextra.GT.0 .OR. rextra.GT.0 ) )
THEN
820 IF( work( j ).LT.work( itmp1 ) )
THEN
825 work( i ) = work( itmp1 )
827 iwork( iwork( m+itmp1 ) ) = i
828 iwork( iwork( m+i ) ) = itmp1
830 iwork( m+i ) = iwork( m+itmp1 )
831 iwork( m+itmp1 ) = itmp2
835 DO 200 j = m - i, lextra + 1, -1
836 IF( work( j ).GT.work( itmp1 ) )
THEN
841 work( m-i+1 ) = work( itmp1 )
843 iwork( iwork( m+itmp1 ) ) = m - i + 1
844 iwork( iwork( 2*m-i+1 ) ) = itmp1
845 itmp2 = iwork( 2*m-i+1 )
846 iwork( 2*m-i+1 ) = iwork( m+itmp1 )
847 iwork( m+itmp1 ) = itmp2
852 IF( iwork( i ).GT.lextra .AND. iwork( i ).LE.m-rextra )
THEN
854 w( j ) = work( iwork( i ) )
855 iblock( j ) = iblock( i )
858 m = m - lextra - rextra
860 IF( m.NE.ilast-ifrst+1 )
THEN
865 CALL blacs_freebuff( onedcontext, 1 )
866 CALL blacs_gridexit( onedcontext )
873 SUBROUTINE pslaebz( IJOB, N, MMAX, MINP, ABSTOL, RELTOL, PIVMIN,
874 $ D, NVAL, INTVL, INTVLCT, MOUT, LSAVE, IEFLAG,
884 INTEGER IEFLAG, IJOB, INFO, MINP, MMAX, MOUT, N
885 REAL ABSTOL, LSAVE, PIVMIN, RELTOL
888 INTEGER INTVLCT( * ), NVAL( * )
889 REAL D( * ), INTVL( * )
1007 INTRINSIC abs, int, log,
max,
min
1013 REAL ZERO, TWO, HALF
1014 parameter( zero = 0.0e+0, two = 2.0e+0,
1015 $ half = 1.0e+0 / two )
1018 INTEGER I, ITMAX, J, K, KF, KL, KLNEW, L, LCNT, LREQ,
1019 $ NALPHA, NBETA, NMID, RCNT, RREQ
1020 REAL ALPHA, BETA, MID
1027 IF( intvl( 2 )-intvl( 1 ).LE.zero )
THEN
1032 IF( ijob.EQ.0 )
THEN
1036 CALL pslaecv( 0, kf, kl, intvl, intvlct, nval,
1037 $
max( abstol, pivmin ), reltol )
1043 itmax = int( ( log( intvl( 2 )-intvl( 1 )+pivmin )-
1044 $ log( pivmin ) ) / log( two ) ) + 2
1050 DO 10 j = kf, kl - 1
1055 mid = half*( intvl( k-1 )+intvl( k ) )
1056 IF( ieflag.EQ.0 )
THEN
1057 CALL pslapdct( mid, n, d, pivmin, nmid )
1059 CALL pslaiect( mid, n, d, nmid )
1064 $ nmid =
min( intvlct( k ),
1065 $
max( intvlct( k-1 ), nmid ) )
1066 IF( nmid.LE.nval( k-1 ) )
THEN
1068 intvlct( k-1 ) = nmid
1070 IF( nmid.GE.nval( k ) )
THEN
1074 IF( nmid.GT.lreq .AND. nmid.LT.rreq )
THEN
1077 intvl( l ) = intvl( k )
1078 intvlct( l-1 ) = nval( k )
1079 intvlct( l ) = intvlct( k )
1081 intvlct( k ) = nval( k-1 )
1082 nval( l-1 ) = nval( k )
1083 nval( l ) = nval( l-1 )
1084 nval( k ) = nval( k-1 )
1089 CALL pslaecv( 0, kf, kl, intvl, intvlct, nval,
1090 $
max( abstol, pivmin ), reltol )
1094 ELSE IF( ijob.EQ.1 )
THEN
1097 nalpha = intvlct( 1 )
1098 nbeta = intvlct( 2 )
1103 IF( nbeta.NE.rreq .AND. beta-alpha.GT.
1104 $
max( abstol, reltol*
max( abs( alpha ), abs( beta ) ) ) )
1109 mid = half*( alpha+beta )
1110 IF( ieflag.EQ.0 )
THEN
1111 CALL pslapdct( mid, n, d, pivmin, nmid )
1113 CALL pslaiect( mid, n, d, nmid )
1115 nmid =
min( nbeta,
max( nalpha, nmid ) )
1116 IF( nmid.GE.rreq )
THEN
1130 intvlct( 1 ) = nalpha
1131 intvlct( 2 ) = nbeta
1132 ELSE IF( ijob.EQ.2 )
THEN
1136 CALL pslaecv( 1, kf, kl, intvl, intvlct, nval,
1137 $
max( abstol, pivmin ), reltol )
1143 itmax = int( ( log( intvl( 2 )-intvl( 1 )+pivmin )-
1144 $ log( pivmin ) ) / log( two ) ) + 2
1150 DO 40 j = kf, kl - 1
1152 mid = half*( intvl( k-1 )+intvl( k ) )
1153 IF( ieflag.EQ.0 )
THEN
1154 CALL pslapdct( mid, n, d, pivmin, nmid )
1156 CALL pslaiect( mid, n, d, nmid )
1158 lcnt = intvlct( k-1 )
1160 nmid =
min( rcnt,
max( lcnt, nmid ) )
1164 IF( nmid.EQ.lcnt )
THEN
1166 ELSE IF( nmid.EQ.rcnt )
THEN
1168 ELSE IF( klnew.LT.mmax+1 )
THEN
1171 intvl( l ) = intvl( k )
1172 intvlct( l-1 ) = nmid
1173 intvlct( l ) = intvlct( k )
1183 CALL pslaecv( 1, kf, kl, intvl, intvlct, nval,
1184 $
max( abstol, pivmin ), reltol )
1190 info =
max( kl-kf, 0 )
1199 SUBROUTINE pslaecv( IJOB, KF, KL, INTVL, INTVLCT, NVAL, ABSTOL,
1209 INTEGER IJOB, KF, KL
1213 INTEGER INTVLCT( * ), NVAL( * )
1295 INTEGER I, ITMP1, ITMP2, J, K, KFNEW
1296 REAL TMP1, TMP2, TMP3, TMP4
1301 DO 10 i = kf, kl - 1
1305 tmp1 = abs( tmp4-tmp3 )
1306 tmp2 =
max( abs( tmp3 ), abs( tmp4 ) )
1307 condn = tmp1.LT.
max( abstol, reltol*tmp2 )
1309 $ condn = condn .OR. ( ( intvlct( k-1 ).EQ.nval( k-1 ) ) .AND.
1310 $ intvlct( k ).EQ.nval( k ) )
1312 IF( i.GT.kfnew )
THEN
1319 itmp1 = intvlct( k-1 )
1320 itmp2 = intvlct( k )
1321 intvl( k-1 ) = intvl( j-1 )
1322 intvl( k ) = intvl( j )
1323 intvlct( k-1 ) = intvlct( j-1 )
1324 intvlct( k ) = intvlct( j )
1327 intvlct( j-1 ) = itmp1
1328 intvlct( j ) = itmp2
1329 IF( ijob.EQ.0 )
THEN
1331 nval( k-1 ) = nval( j-1 )
1334 nval( k ) = nval( j )
1348 SUBROUTINE pslapdct( SIGMA, N, D, PIVMIN, COUNT )
1416 PARAMETER ( ZERO = 0.0e+0 )
1424 tmp = d( 1 ) - sigma
1425 IF( abs( tmp ).LE.pivmin )
1430 DO 10 i = 3, 2*n - 1, 2
1431 tmp = d( i ) - d( i-1 ) / tmp - sigma
1432 IF( abs( tmp ).LE.pivmin )