1 SUBROUTINE pdstebz( 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,
14 DOUBLE PRECISION ABSTOL, VL, VU
17 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
18 DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )
210 INTRINSIC abs, dble, ichar,
max,
min, mod
215 DOUBLE PRECISION PDLAMCH
216 EXTERNAL lsame, blacs_pnum, pdlamch
219 EXTERNAL blacs_freebuff, blacs_get, blacs_gridexit,
220 $ blacs_gridinfo, blacs_gridmap, dgebr2d,
222 $ igebr2d, igebs2d, igerv2d, igesd2d, igsum2d,
227 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
228 $ MB_, NB_, RSRC_, CSRC_, LLD_
229 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
230 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
231 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
232 INTEGER BIGNUM, DESCMULT
233 PARAMETER ( BIGNUM = 10000, descmult = 100 )
234 DOUBLE PRECISION ZERO, ONE, TWO, FIVE, HALF
235 parameter( zero = 0.0d+0, one = 1.0d+0, two = 2.0d+0,
236 $ five = 5.0d+0, half = 1.0d+0 / two )
237 DOUBLE PRECISION FUDGE, RELFAC
238 PARAMETER ( FUDGE = 2.0d+0, relfac = 2.0d+0 )
242 INTEGER BLKNO, FOUND, I, IBEGIN, IEFLAG, IEND, IFRST,
243 $ iinfo, ilast, iload, im, imyload, in, indriw1,
244 $ indriw2, indrw1, indrw2, inxtload, ioff,
245 $ iorder, iout, irange, irecv, irem, itmp1,
246 $ itmp2, j, jb, k, last, lextra, lreq, mycol,
247 $ myrow, nalpha, nbeta, ncmp, neigint, next, ngl,
248 $ nglob, ngu, nint, npcol, nprow, offset,
249 $ onedcontext, p, prev, rextra, rreq, self,
251 DOUBLE PRECISION ALPHA, ATOLI, BETA, BNORM, DRECV, DSEND, GL,
252 $ GU, INITVL, INITVU, LSAVE, MID, PIVMIN, RELTOL,
253 $ safemn, tmp1, tmp2, tnorm, ulp
260 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
265 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
272 IF( lsame( range,
'A' ) )
THEN
274 ELSE IF( lsame( range,
'V' ) )
THEN
276 ELSE IF( lsame( range,
'I' ) )
THEN
284 IF( lsame( order,
'B' ) )
THEN
286 ELSE IF( lsame( order,
'E' ) .OR. lsame( order,
'A' ) )
THEN
294 IF( nprow.EQ.-1 )
THEN
300 safemn = pdlamch( ictxt,
'S' )
301 ulp = pdlamch( ictxt,
'P' )
303 idum( 1, 1 ) = ichar( range )
305 idum( 2, 1 ) = ichar( order )
310 IF( irange.EQ.3 )
THEN
321 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
THEN
323 IF( irange.EQ.2 )
THEN
330 CALL dgebs2d( ictxt,
'ALL',
' ', 3, 1, work, 3 )
332 CALL dgebr2d( ictxt,
'ALL',
' ', 3, 1, work, 3, 0, 0 )
334 lquery = ( lwork.EQ.-1 .OR. liwork.EQ.-1 )
336 IF( irange.EQ.0 )
THEN
338 ELSE IF( iorder.EQ.0 )
THEN
340 ELSE IF( irange.EQ.2 .AND. vl.GE.vu )
THEN
342 ELSE IF( irange.EQ.3 .AND. ( il.LT.1 .OR. il.GT.
max( 1,
345 ELSE IF( irange.EQ.3 .AND. ( iu.LT.
min( n,
346 $ il ) .OR. iu.GT.n ) )
THEN
348 ELSE IF( lwork.LT.
max( 5*n, 7 ) .AND. .NOT.lquery )
THEN
350 ELSE IF( liwork.LT.
max( 4*n, 14, nprow*npcol ) .AND. .NOT.
353 ELSE IF( irange.EQ.2 .AND. ( abs( work( 2 )-vl ).GT.five*
354 $ ulp*abs( vl ) ) )
THEN
356 ELSE IF( irange.EQ.2 .AND. ( abs( work( 3 )-vu ).GT.five*
357 $ ulp*abs( vu ) ) )
THEN
359 ELSE IF( abs( work( 1 )-abstol ).GT.five*ulp*abs( abstol ) )
366 CALL globchk( ictxt, nglob, idum, 5, iwork, info )
367 IF( info.EQ.bignum )
THEN
369 ELSE IF( mod( info, descmult ).EQ.0 )
THEN
370 info = -info / descmult
375 work( 1 ) = dble(
max( 5*n, 7 ) )
376 iwork( 1 ) =
max( 4*n, 14, nprow*npcol )
379 CALL pxerbla( ictxt,
'PDSTEBZ', -info )
381 ELSE IF( lwork.EQ.-1 .AND. liwork.EQ.-1 )
THEN
392 DO 20 i = 0, nprow - 1
393 DO 10 j = 0, npcol - 1
394 iwork( k ) = blacs_pnum( ictxt, i, j )
403 CALL blacs_get( ictxt, 10, onedcontext )
404 CALL blacs_gridmap( onedcontext, iwork, nprow, nprow, npcol )
405 CALL blacs_gridinfo( onedcontext, i, j, k, self )
409 IF( irange.EQ.3 .AND. il.EQ.1 .AND. iu.EQ.n )
412 next = mod( self+1, p )
413 prev = mod( p+self-1, p )
418 indrw1 =
max( 2*n, 4 )
419 indrw2 = indrw1 + 2*n
420 indriw1 =
max( 2*n, 8 )
422 work( indrw1+2*n ) = zero
428 work( indrw1+j-1 ) = d( i )
429 IF( abs( d( i+1 )*d( i ) )*ulp**2+safemn.GT.tmp1 )
THEN
432 work( indrw1+j ) = zero
434 work( indrw1+j ) = tmp1
435 pivmin =
max( pivmin, tmp1 )
438 work( indrw1+2*n-1 ) = d( n )
440 pivmin = pivmin*safemn
450 gu =
max( gu, d( i )+tmp1+tmp2 )
451 gl =
min( gl, d( i )-tmp1-tmp2 )
454 gu =
max( gu, d( n )+tmp1 )
455 gl =
min( gl, d( n )-tmp1 )
456 tnorm =
max( abs( gl ), abs( gu ) )
457 gl = gl - fudge*tnorm*ulp*n - fudge*two*pivmin
458 gu = gu + fudge*tnorm*ulp*n + fudge*pivmin
460 IF( abstol.LE.zero )
THEN
469 IF( irange.EQ.1 .OR. nsplit.EQ.1 )
THEN
470 CALL pdlasnbt( ieflag )
479 IF( irange.EQ.1 )
THEN
488 ELSE IF( irange.EQ.2 )
THEN
490 IF( ieflag.EQ.0 )
THEN
491 CALL pdlapdct( vl, n, work( indrw1+1 ), pivmin, ifrst )
492 ELSE IF( ieflag.EQ.1 )
THEN
493 CALL pdlaiectb( vl, n, work( indrw1+1 ), ifrst )
495 CALL pdlaiectl( vl, n, work( indrw1+1 ), ifrst )
504 IF( ieflag.EQ.0 )
THEN
505 CALL pdlapdct( vu, n, work( indrw1+1 ), pivmin, ilast )
506 ELSE IF( ieflag.EQ.1 )
THEN
507 CALL pdlaiectb( vu, n, work( indrw1+1 ), ilast )
509 CALL pdlaiectl( vu, n, work( indrw1+1 ), ilast )
518 iwork( 1 ) = ifrst - 1
520 ELSE IF( irange.EQ.3 )
THEN
527 CALL pdlaebz( 0, n, 2, 1, atoli, reltol, pivmin,
528 $ work( indrw1+1 ), iwork( 5 ), work, iwork, nint,
529 $ lsave, ieflag, iinfo )
530 IF( iinfo.NE.0 )
THEN
535 IF( iwork( 5 ).EQ.il-1 )
THEN
536 work( 2 ) = work( 4 )
537 iwork( 2 ) = iwork( 4 )
539 work( 1 ) = work( 3 )
540 iwork( 1 ) = iwork( 3 )
542 IF( iwork( 1 ).LT.0 .OR. iwork( 1 ).GT.il-1 .OR.
543 $ iwork( 2 ).LE.
min( iu-1, iwork( 1 ) ) .OR.
544 $ iwork( 2 ).GT.n )
THEN
549 lextra = il - 1 - iwork( 1 )
550 rextra = iwork( 2 ) - iu
564 indriw2 = indriw1 + ngu - ngl
568 IF( ifrst.EQ.1 .AND. ilast.EQ.n )
579 IF( irange.NE.1 )
THEN
584 CALL igsum2d( onedcontext,
'All',
' ', 1, 1, found, 1,
600 DO 50 j = ibegin, iend - 1
602 gu =
max( gu, d( j )+tmp1+tmp2 )
603 gl =
min( gl, d( j )-tmp1-tmp2 )
607 gu =
max( gu, d( iend )+tmp1 )
608 gl =
min( gl, d( iend )-tmp1 )
609 bnorm =
max( abs( gl ), abs( gu ) )
610 gl = gl - fudge*bnorm*ulp*in - fudge*pivmin
611 gu = gu + fudge*bnorm*ulp*in + fudge*pivmin
615 IF( abstol.LE.zero )
THEN
621 IF( gl.LT.initvl )
THEN
623 IF( ieflag.EQ.0 )
THEN
624 CALL pdlapdct( gl, in, work( indrw1+2*ioff+1 ),
626 ELSE IF( ieflag.EQ.1 )
THEN
627 CALL pdlaiectb( gl, in, work( indrw1+2*ioff+1 ), ngl )
629 CALL pdlaiectl( gl, in, work( indrw1+2*ioff+1 ), ngl )
634 IF( gu.GT.initvu )
THEN
636 IF( ieflag.EQ.0 )
THEN
637 CALL pdlapdct( gu, in, work( indrw1+2*ioff+1 ),
639 ELSE IF( ieflag.EQ.1 )
THEN
640 CALL pdlaiectb( gu, in, work( indrw1+2*ioff+1 ), ngu )
642 CALL pdlaiectl( gu, in, work( indrw1+2*ioff+1 ), ngu )
662 irem = ncmp - iload*p
663 itmp1 = mod( self-found, p )
666 IF( itmp1.LT.irem )
THEN
671 IF( imyload.EQ.0 )
THEN
673 ELSE IF( in.EQ.1 )
THEN
674 work( indrw2+im+1 ) = work( indrw1+2*ioff+1 )
675 iwork( indriw1+im+1 ) = blkno
676 iwork( indriw2+im+1 ) = offset + 1
681 itmp2 = mod( self+1-found, p )
685 $ inxtload = inxtload + 1
686 lreq = ngl + itmp1*iload +
min( irem, itmp1 )
687 rreq = lreq + imyload
692 CALL pdlaebz( 1, in, 1, 1, atoli, reltol, pivmin,
693 $ work( indrw1+2*ioff+1 ), iwork( 5 ), work,
694 $ iwork, nint, lsave, ieflag, iinfo )
700 IF( nbeta.GT.rreq+inxtload )
THEN
704 last = mod( found+
min( ngu-ngl, p )-1, p )
707 IF( self.NE.last )
THEN
708 CALL dgesd2d( onedcontext, 1, 1, dsend, 1, 0, next )
709 CALL igesd2d( onedcontext, 1, 1, nbeta, 1, 0, next )
711 IF( self.NE.mod( found, p ) )
THEN
712 CALL dgerv2d( onedcontext, 1, 1, drecv, 1, 0, prev )
713 CALL igerv2d( onedcontext, 1, 1, irecv, 1, 0, prev )
718 work( 1 ) =
max( lsave, drecv )
720 alpha =
max( alpha, work( 1 ) )
721 nalpha =
max( nalpha, irecv )
722 IF( beta-alpha.LE.
max( atoli, reltol*
max( abs( alpha ),
723 $ abs( beta ) ) ) )
THEN
724 mid = half*( alpha+beta )
725 DO 60 j = offset + nalpha + 1, offset + nbeta
726 work( indrw2+im+1 ) = mid
727 iwork( indriw1+im+1 ) = blkno
728 iwork( indriw2+im+1 ) = j
735 neigint = iwork( 2 ) - iwork( 1 )
741 CALL pdlaebz( 2, in, neigint, 1, atoli, reltol, pivmin,
742 $ work( indrw1+2*ioff+1 ), iwork, work, iwork,
743 $ iout, lsave, ieflag, iinfo )
744 IF( iinfo.NE.0 )
THEN
748 mid = half*( work( 2*i-1 )+work( 2*i ) )
749 IF( i.GT.iout-iinfo )
751 DO 70 j = offset + iwork( 2*i-1 ) + 1,
752 $ offset + iwork( 2*i )
753 work( indrw2+im+1 ) = mid
754 iwork( indriw1+im+1 ) = blkno
755 iwork( indriw2+im+1 ) = j
765 CALL igsum2d( onedcontext,
'ALL',
' ', 1, 1, m, 1, -1, -1 )
770 IF( self.EQ.i-1 )
THEN
771 CALL igebs2d( onedcontext,
'ALL',
' ', 1, 1, im, 1 )
773 CALL igebs2d( onedcontext,
'ALL',
' ', im, 1,
774 $ iwork( indriw2+1 ), im )
775 CALL dgebs2d( onedcontext,
'ALL',
' ', im, 1,
776 $ work( indrw2+1 ), im )
777 CALL igebs2d( onedcontext,
'ALL',
' ', im, 1,
778 $ iwork( indriw1+1 ), im )
780 w( iwork( indriw2+j ) ) = work( indrw2+j )
781 iblock( iwork( indriw2+j ) ) = iwork( indriw1+j )
785 CALL igebr2d( onedcontext,
'ALL',
' ', 1, 1, torecv, 1, 0,
787 IF( torecv.NE.0 )
THEN
788 CALL igebr2d( onedcontext,
'ALL',
' ', torecv, 1, iwork,
790 CALL dgebr2d( onedcontext,
'ALL',
' ', torecv, 1, work,
792 CALL igebr2d( onedcontext,
'ALL',
' ', torecv, 1,
793 $ iwork( n+1 ), torecv, 0, i-1 )
795 w( iwork( j ) ) = work( j )
796 iblock( iwork( j ) ) = iwork( n+j )
801 IF( nsplit.GT.1 .AND. iorder.EQ.1 )
THEN
809 CALL dlasrt2(
'I', m, w, iwork( m+1 ), iinfo )
811 iwork( i ) = iblock( i )
814 iblock( i ) = iwork( iwork( m+i ) )
817 IF( irange.EQ.3 .AND. ( lextra.GT.0 .OR. rextra.GT.0 ) )
THEN
830 IF( work( j ).LT.work( itmp1 ) )
THEN
835 work( i ) = work( itmp1 )
837 iwork( iwork( m+itmp1 ) ) = i
838 iwork( iwork( m+i ) ) = itmp1
840 iwork( m+i ) = iwork( m+itmp1 )
841 iwork( m+itmp1 ) = itmp2
845 DO 200 j = m - i, lextra + 1, -1
846 IF( work( j ).GT.work( itmp1 ) )
THEN
851 work( m-i+1 ) = work( itmp1 )
853 iwork( iwork( m+itmp1 ) ) = m - i + 1
854 iwork( iwork( 2*m-i+1 ) ) = itmp1
855 itmp2 = iwork( 2*m-i+1 )
856 iwork( 2*m-i+1 ) = iwork( m+itmp1 )
857 iwork( m+itmp1 ) = itmp2
862 IF( iwork( i ).GT.lextra .AND. iwork( i ).LE.m-rextra )
THEN
864 w( j ) = work( iwork( i ) )
865 iblock( j ) = iblock( i )
868 m = m - lextra - rextra
870 IF( m.NE.ilast-ifrst+1 )
THEN
875 CALL blacs_freebuff( onedcontext, 1 )
876 CALL blacs_gridexit( onedcontext )
883 SUBROUTINE pdlaebz( IJOB, N, MMAX, MINP, ABSTOL, RELTOL, PIVMIN,
884 $ D, NVAL, INTVL, INTVLCT, MOUT, LSAVE, IEFLAG,
894 INTEGER IEFLAG, IJOB, INFO, MINP, MMAX, MOUT, N
895 DOUBLE PRECISION ABSTOL, LSAVE, PIVMIN, RELTOL
898 INTEGER INTVLCT( * ), NVAL( * )
899 DOUBLE PRECISION D( * ), INTVL( * )
1017 INTRINSIC abs, int, log,
max,
min
1023 DOUBLE PRECISION ZERO, TWO, HALF
1024 parameter( zero = 0.0d+0, two = 2.0d+0,
1025 $ half = 1.0d+0 / two )
1028 INTEGER I, ITMAX, J, K, KF, KL, KLNEW, L, LCNT, LREQ,
1029 $ NALPHA, NBETA, NMID, RCNT, RREQ
1030 DOUBLE PRECISION ALPHA, BETA, MID
1037 IF( intvl( 2 )-intvl( 1 ).LE.zero )
THEN
1042 IF( ijob.EQ.0 )
THEN
1046 CALL pdlaecv( 0, kf, kl, intvl, intvlct, nval,
1047 $
max( abstol, pivmin ), reltol )
1053 itmax = int( ( log( intvl( 2 )-intvl( 1 )+pivmin )-
1054 $ log( pivmin ) ) / log( two ) ) + 2
1060 DO 10 j = kf, kl - 1
1065 mid = half*( intvl( k-1 )+intvl( k ) )
1066 IF( ieflag.EQ.0 )
THEN
1067 CALL pdlapdct( mid, n, d, pivmin, nmid )
1068 ELSE IF( ieflag.EQ.1 )
THEN
1069 CALL pdlaiectb( mid, n, d, nmid )
1071 CALL pdlaiectl( mid, n, d, nmid )
1076 $ nmid =
min( intvlct( k ),
1077 $
max( intvlct( k-1 ), nmid ) )
1078 IF( nmid.LE.nval( k-1 ) )
THEN
1080 intvlct( k-1 ) = nmid
1082 IF( nmid.GE.nval( k ) )
THEN
1086 IF( nmid.GT.lreq .AND. nmid.LT.rreq )
THEN
1089 intvl( l ) = intvl( k )
1090 intvlct( l-1 ) = nval( k )
1091 intvlct( l ) = intvlct( k )
1093 intvlct( k ) = nval( k-1 )
1094 nval( l-1 ) = nval( k )
1095 nval( l ) = nval( l-1 )
1096 nval( k ) = nval( k-1 )
1101 CALL pdlaecv( 0, kf, kl, intvl, intvlct, nval,
1102 $
max( abstol, pivmin ), reltol )
1106 ELSE IF( ijob.EQ.1 )
THEN
1109 nalpha = intvlct( 1 )
1110 nbeta = intvlct( 2 )
1115 IF( nbeta.NE.rreq .AND. beta-alpha.GT.
1116 $
max( abstol, reltol*
max( abs( alpha ), abs( beta ) ) ) )
1121 mid = half*( alpha+beta )
1122 IF( ieflag.EQ.0 )
THEN
1123 CALL pdlapdct( mid, n, d, pivmin, nmid )
1124 ELSE IF( ieflag.EQ.1 )
THEN
1125 CALL pdlaiectb( mid, n, d, nmid )
1127 CALL pdlaiectl( mid, n, d, nmid )
1129 nmid =
min( nbeta,
max( nalpha, nmid ) )
1130 IF( nmid.GE.rreq )
THEN
1144 intvlct( 1 ) = nalpha
1145 intvlct( 2 ) = nbeta
1146 ELSE IF( ijob.EQ.2 )
THEN
1150 CALL pdlaecv( 1, kf, kl, intvl, intvlct, nval,
1151 $
max( abstol, pivmin ), reltol )
1157 itmax = int( ( log( intvl( 2 )-intvl( 1 )+pivmin )-
1158 $ log( pivmin ) ) / log( two ) ) + 2
1164 DO 40 j = kf, kl - 1
1166 mid = half*( intvl( k-1 )+intvl( k ) )
1167 IF( ieflag.EQ.0 )
THEN
1168 CALL pdlapdct( mid, n, d, pivmin, nmid )
1169 ELSE IF( ieflag.EQ.1 )
THEN
1170 CALL pdlaiectb( mid, n, d, nmid )
1172 CALL pdlaiectl( mid, n, d, nmid )
1174 lcnt = intvlct( k-1 )
1176 nmid =
min( rcnt,
max( lcnt, nmid ) )
1180 IF( nmid.EQ.lcnt )
THEN
1182 ELSE IF( nmid.EQ.rcnt )
THEN
1184 ELSE IF( klnew.LT.mmax+1 )
THEN
1187 intvl( l ) = intvl( k )
1188 intvlct( l-1 ) = nmid
1189 intvlct( l ) = intvlct( k )
1199 CALL pdlaecv( 1, kf, kl, intvl, intvlct, nval,
1200 $
max( abstol, pivmin ), reltol )
1206 info =
max( kl-kf, 0 )
1215 SUBROUTINE pdlaecv( IJOB, KF, KL, INTVL, INTVLCT, NVAL, ABSTOL,
1225 INTEGER IJOB, KF, KL
1226 DOUBLE PRECISION ABSTOL, RELTOL
1229 INTEGER INTVLCT( * ), NVAL( * )
1230 DOUBLE PRECISION INTVL( * )
1311 INTEGER I, ITMP1, ITMP2, J, K, KFNEW
1312 DOUBLE PRECISION TMP1, TMP2, TMP3, TMP4
1317 DO 10 i = kf, kl - 1
1321 tmp1 = abs( tmp4-tmp3 )
1322 tmp2 =
max( abs( tmp3 ), abs( tmp4 ) )
1323 condn = tmp1.LT.
max( abstol, reltol*tmp2 )
1325 $ condn = condn .OR. ( ( intvlct( k-1 ).EQ.nval( k-1 ) ) .AND.
1326 $ intvlct( k ).EQ.nval( k ) )
1328 IF( i.GT.kfnew )
THEN
1335 itmp1 = intvlct( k-1 )
1336 itmp2 = intvlct( k )
1337 intvl( k-1 ) = intvl( j-1 )
1338 intvl( k ) = intvl( j )
1339 intvlct( k-1 ) = intvlct( j-1 )
1340 intvlct( k ) = intvlct( j )
1343 intvlct( j-1 ) = itmp1
1344 intvlct( j ) = itmp2
1345 IF( ijob.EQ.0 )
THEN
1347 nval( k-1 ) = nval( j-1 )
1350 nval( k ) = nval( j )
1364 SUBROUTINE pdlapdct( SIGMA, N, D, PIVMIN, COUNT )
1374 DOUBLE PRECISION PIVMIN, SIGMA
1377 DOUBLE PRECISION D( * )
1431 DOUBLE PRECISION ZERO
1432 PARAMETER ( ZERO = 0.0d+0 )
1436 DOUBLE PRECISION TMP
1440 tmp = d( 1 ) - sigma
1441 IF( abs( tmp ).LE.pivmin )
1446 DO 10 i = 3, 2*n - 1, 2
1447 tmp = d( i ) - d( i-1 ) / tmp - sigma
1448 IF( abs( tmp ).LE.pivmin )