1 SUBROUTINE pzseprsubtst( WKNOWN, JOBZ, RANGE, UPLO, N, VL, VU, IL,
2 $ IU, THRESH, ABSTOL, A, COPYA, Z, IA, JA,
3 $ DESCA, WIN, WNEW, IFAIL, ICLUSTR, GAP,
4 $ IPREPAD, IPOSTPAD, WORK, LWORK, RWORK,
5 $ LRWORK, LWORK1, IWORK, LIWORK, RESULT,
6 $ TSTNRM, QTQNRM, NOUT )
17 CHARACTER JOBZ, RANGE, UPLO
18 INTEGER IA, IL, IPOSTPAD, IPREPAD, IU, JA, LIWORK,
19 $ LWORK, LWORK1, N, NOUT, RESULT
20 DOUBLE PRECISION ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
24 INTEGER DESCA( * ), ICLUSTR( * ), IFAIL( * ),
26 COMPLEX*16 A( * ), COPYA( * ), WORK( * ), Z( * )
27 DOUBLE PRECISION GAP( * ), RWORK( * ), WIN( * ), WNEW( * )
195 INTEGER DLEN_, CTXT_, M_, N_,
196 $ MB_, NB_, RSRC_, CSRC_, LLD_
197 PARAMETER ( DLEN_ = 9,
198 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
199 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
200 DOUBLE PRECISION PADVAL, FIVE, NEGONE
201 PARAMETER ( PADVAL = 13.5285d0, five = 5.0d0,
204 PARAMETER ( ZPADVAL = ( 13.989d0, 1.93d0 ) )
206 parameter( ipadval = 927 )
209 LOGICAL MISSLARGEST, MISSSMALLEST
210 INTEGER I, IAM, INDIWRK, INFO, ISIZESUBTST, ISIZEEVR,
211 $ isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
212 $ minil, mq, mycol, myil, myrow, nclusters, np,
213 $ npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
214 $ sizechk, sizemqrleft, sizemqrright, sizeqrf,
215 $ sizeqtq, sizesubtst, sizeevr, sizetms,
216 $ sizetst, valsize, vecsize
217 INTEGER RSIZEEVR, RSIZESUBTST, RSIZETST
218 DOUBLE PRECISION EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
219 $ MINERROR, MINVL, NORMWIN, OLDVL, OLDVU,
223 INTEGER DESCZ( DLEN_ ), ISEED( 4 ), ITMP( 2 )
229 DOUBLE PRECISION PDLAMCH, PZLANHE
230 EXTERNAL LSAME, NUMROC, PDLAMCH, PZLANHE
233 EXTERNAL blacs_gridinfo,
descinit, dgamn2d, dgamx2d,
241 INTRINSIC abs,
max,
min, mod
245 CALL pzlasizesepr( desca, iprepad, ipostpad, sizemqrleft,
246 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
247 $ sizechk, sizeevr, rsizeevr, isizeevr,
248 $ sizesubtst, rsizesubtst, isizesubtst,
249 $ sizetst, rsizetst, isizetst )
253 eps = pdlamch( desca( ctxt_ ),
'Eps' )
254 safmin = pdlamch( desca( ctxt_ ),
'Safe min' )
256 normwin = safmin / eps
258 $ normwin =
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
269 DO 10 i = 1, lwork1, 1
270 rwork( i+iprepad ) = 14.3d0
273 DO 15 i = 1, lwork, 1
274 work( i+iprepad ) = ( 15.63d0, 1.1d0 )
277 DO 20 i = 1, liwork, 1
278 iwork( i+iprepad ) = 14
282 wnew( i+iprepad ) = 3.14159d0
285 iclustr( 1+iprepad ) = 139
287 IF (lsame( range,
'V' ) )
THEN
291 IF( lsame( jobz,
'N' ) )
THEN
294 IF( lsame( range,
'A' ) )
THEN
296 ELSE IF( lsame( range,
'I' ) )
THEN
297 maxeigs = iu - il + 1
299 minvl = vl - normwin*five*eps - abstol
300 maxvu = vu + normwin*five*eps + abstol
306 IF( win( i ).LT.minvl )
308 IF( win( i ).LE.maxvu )
312 maxeigs = maxiu - minil + 1
317 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
318 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
319 $ desca( ctxt_ ), desca( lld_ ), info )
321 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
322 indiwrk = 1 + iprepad + nprow*npcol + 1
325 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
331 IF( myrow.GE.nprow .OR. myrow.LT.0 )
338 $ iseed, win, maxsize, vecsize, valsize )
340 np = numroc( n, desca( mb_ ), myrow, 0, nprow )
341 nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
342 mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
344 CALL zlacpy(
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
347 CALL pzfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
348 $ ipostpad, zpadval )
350 CALL pzfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
351 $ ipostpad, zpadval+1.0d0 )
359 CALL pdfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
362 CALL pdfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
363 $ iprepad, ipostpad, padval+3.0d0 )
365 CALL pdfillpad( desca( ctxt_ ), lwork1, 1, rwork,lwork1, iprepad,
366 $ ipostpad, padval+4.0d0 )
368 CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
369 $ ipostpad, ipadval )
371 CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
374 CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
375 $ 2*nprow*npcol, iprepad, ipostpad, ipadval )
377 CALL pzfillpad( desca( ctxt_ ), lwork, 1, work, lwork, iprepad,
378 $ ipostpad, zpadval+4.1d0 )
384 DO 50 j = 1, maxeigs, 1
385 CALL pzelset( z( 1+iprepad ), i, j, desca,
386 $ ( 13.0d0, 1.34d0 ) )
400 CALL pzheevr( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
401 $ vl, vu, il, iu, m, nz, wnew( 1+iprepad ),
402 $ z( 1+iprepad ), ia, ja, desca,
403 $ work( 1+iprepad ), sizeevr,
404 $ rwork( 1+iprepad ), lwork1,
405 $ iwork( 1+iprepad ), liwork, info )
418 iclustr( 1+iprepad ) = 0
420 IF( thresh.LE.0 )
THEN
423 CALL pzchekpad( desca( ctxt_ ),
'PZHEEVR-A', np, nq, a,
424 $ desca( lld_ ), iprepad, ipostpad, zpadval )
426 CALL pzchekpad( descz( ctxt_ ),
'PZHEEVR-Z', np, mq, z,
427 $ descz( lld_ ), iprepad, ipostpad,
430 CALL pdchekpad( desca( ctxt_ ),
'PZHEEVR-WNEW', n, 1, wnew, n,
431 $ iprepad, ipostpad, padval+2.0d0 )
433 CALL pdchekpad( desca( ctxt_ ),
'PZHEEVR-GAP', nprow*npcol, 1,
434 $ gap, nprow*npcol, iprepad, ipostpad,
437 CALL pdchekpad( desca( ctxt_ ),
'PZHEEVR-RWORK',lwork1, 1,
438 $ rwork, lwork1, iprepad, ipostpad,
441 CALL pzchekpad( desca( ctxt_ ),
'PZHEEVR-WORK',lwork, 1,
442 $ work, lwork, iprepad, ipostpad,
445 CALL pichekpad( desca( ctxt_ ),
'PZHEEVR-IWORK', liwork, 1,
446 $ iwork, liwork, iprepad, ipostpad, ipadval )
448 CALL pichekpad( desca( ctxt_ ),
'PZHEEVR-IFAIL', n, 1, ifail,
449 $ n, iprepad, ipostpad, ipadval )
451 CALL pichekpad( desca( ctxt_ ),
'PZHEEVR-ICLUSTR',
452 $ 2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
453 $ iprepad, ipostpad, ipadval )
457 IF( lsame( range,
'A' ) )
THEN
459 $ iseed, wnew( 1+iprepad ), maxsize,
469 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
471 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1, 1,
475 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
477 $
WRITE( nout, fmt = * )
478 $
'Different processes return different INFO'
480 ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
483 $
WRITE( nout, fmt = 9999 )info
485 ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize )
THEN
487 $
WRITE( nout, fmt = 9996 )info
489 ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize )
THEN
491 $
WRITE( nout, fmt = 9996 )info
495 IF( lsame( jobz,
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
496 $ 0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) )
THEN
498 $
WRITE( nout, fmt = 9995 )
504 IF( ( m.LT.0 ) .OR. ( m.GT.n ) )
THEN
506 $
WRITE( nout, fmt = 9994 )
507 WRITE( nout,*)
'M = ', m,
'\n',
'N = ', n
509 ELSE IF( lsame( range,
'A' ) .AND. ( m.NE.n ) )
THEN
511 $
WRITE( nout, fmt = 9993 )
513 ELSE IF( lsame( range,
'I' ) .AND. ( m.NE.iu-il+1 ) )
THEN
515 WRITE( nout, fmt = 9992 )
516 WRITE( nout,*)
'IL = ', il,
' IU = ', iu,
' M = ', m
519 ELSE IF( lsame( jobz,
'V' ) .AND.
520 $ ( .NOT.( lsame( range,
'V' ) ) ) .AND. ( m.NE.nz ) )
523 $
WRITE( nout, fmt = 9991 )
529 IF( lsame( jobz,
'V' ) )
THEN
530 IF( lsame( range,
'V' ) )
THEN
533 $
WRITE( nout, fmt = 9990 )
536 IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 )
THEN
538 $
WRITE( nout, fmt = 9989 )
544 $
WRITE( nout, fmt = 9988 )
549 IF( result.EQ.0 )
THEN
556 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
558 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
561 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
563 $
WRITE( nout, fmt = 9987 )
570 rwork( i ) = wnew( i+iprepad )
571 rwork( i+m ) = wnew( i+iprepad )
574 CALL dgamn2d( desca( ctxt_ ),
'a',
' ', m, 1, rwork, m,
576 CALL dgamx2d( desca( ctxt_ ),
'a',
' ', m, 1,
577 $ rwork( 1+m ), m, 1, 1, -1, -1, 0 )
580 IF( result.EQ.0 .AND. ( abs( rwork( i )-rwork( m+
581 $ i ) ).GT.five*eps*abs( rwork( i ) ) ) )
THEN
583 $
WRITE( nout, fmt = 9986 )
592 IF( lsame( jobz,
'V' ) )
THEN
594 DO 90 i = 0, nprow*npcol - 1
595 IF( iclustr( 1+iprepad+2*i ).EQ.0 )
597 nclusters = nclusters + 1
600 itmp( 1 ) = nclusters
601 itmp( 2 ) = nclusters
603 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
605 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
608 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
610 $
WRITE( nout, fmt = 9985 )
616 DO 110 i = 1, nclusters
617 iwork( indiwrk+i ) = iclustr( i+iprepad )
618 iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
620 CALL igamn2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
621 $ iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
623 CALL igamx2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
624 $ iwork( indiwrk+1+nclusters ),
625 $ nclusters*2+1, 1, 1, -1, -1, 0 )
627 DO 120 i = 1, nclusters
628 IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
629 $ iwork( indiwrk+nclusters+i ) )
THEN
631 $
WRITE( nout, fmt = 9984 )
636 IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 )
THEN
638 $
WRITE( nout, fmt = 9983 )
644 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1,
654 epsnorma = pzlanhe(
'I', uplo, n, copya, ia, ja, desca,
658 IF( lsame( jobz,
'V' ) )
THEN
662 CALL pdfillpad( desca( ctxt_ ), sizechk, 1, rwork,sizechk,
663 $ iprepad, ipostpad, 4.3d0 )
665 CALL pzsepchk( n, nz, copya, ia, ja, desca,
666 $
max( abstol+epsnorma, safmin ), thresh,
667 $ z( 1+iprepad ), ia, ja, descz,
668 $ a( 1+iprepad ), ia, ja, desca,
669 $ wnew( 1+iprepad ), rwork( 1+iprepad ),
670 $ sizechk, tstnrm, res )
672 CALL pdchekpad( desca( ctxt_ ),
'PZSEPCHK-RWORK',sizechk, 1,
673 $ rwork,sizechk, iprepad, ipostpad, 4.3d0 )
680 CALL pdfillpad( desca( ctxt_ ), sizeqtq, 1,rwork, sizeqtq,
681 $ iprepad, ipostpad, 4.3d0 )
684 CALL pzsepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
685 $ a( 1+iprepad ), ia, ja, desca,
686 $ iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
687 $ gap( 1+iprepad ),rwork( iprepad+1 ), sizeqtq,
688 $ qtqnrm, info, res )
690 CALL pdchekpad( desca( ctxt_ ),
'PDSEPQTQ-RWORK',sizeqtq, 1,
691 $ rwork,sizeqtq, iprepad, ipostpad, 4.3d0 )
698 $
WRITE( nout, fmt = 9998 )info
709 IF( lsame( range,
'V' ) )
THEN
714 IF( lsame( range,
'A' ) )
THEN
726 DO 140 myil = minil, maxil
731 misssmallest = .true.
732 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.1 ) )
733 $ misssmallest = .false.
734 IF( misssmallest .AND. ( win( myil-1 ).LT.vl+normwin*
735 $ five*thresh*eps ) )misssmallest = .false.
737 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.maxil ) )
738 $ misslargest = .false.
739 IF( misslargest .AND. ( win( myil+m ).GT.vu-normwin*five*
740 $ thresh*eps ) )misslargest = .false.
741 IF( .NOT.misssmallest )
THEN
742 IF( .NOT.misslargest )
THEN
749 error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
750 maxerror =
max( maxerror, error )
753 minerror =
min( maxerror, minerror )
763 IF( lsame( jobz,
'V' ) .AND. lsame( range,
'A' ) )
THEN
764 IF( minerror.GT.normwin*five*five*thresh*eps )
THEN
766 $
WRITE( nout, fmt = 9997 )minerror, normwin
770 IF( minerror.GT.normwin*five*thresh*eps )
THEN
772 $
WRITE( nout, fmt = 9997 )minerror, normwin
780 IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
783 $
WRITE( nout, fmt = 9982 )
787 IF( lsame( jobz,
'N' ) .AND. ( nz.NE.oldnz ) )
THEN
789 $
WRITE( nout, fmt = 9981 )
797 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1, -1,
804 9999
FORMAT(
'PZHEEVR returned INFO=', i7 )
805 9998
FORMAT(
'PZSEPQTQ returned INFO=', i7 )
806 9997
FORMAT(
'PZSEPRSUBTST minerror =', d11.2,
' normwin=', d11.2 )
807 9996
FORMAT(
'PZHEEVR returned INFO=', i7,
808 $
' despite adequate workspace' )
809 9995
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
810 9994
FORMAT(
'M not in the range 0 to N' )
811 9993
FORMAT(
'M not equal to N' )
812 9992
FORMAT(
'M not equal to IU-IL+1' )
813 9991
FORMAT(
'M not equal to NZ' )
814 9990
FORMAT(
'NZ > M' )
815 9989
FORMAT(
'NZ < M' )
816 9988
FORMAT(
'NZ not equal to M' )
817 9987
FORMAT(
'Different processes return different values for M' )
818 9986
FORMAT(
'Different processes return different eigenvalues' )
819 9985
FORMAT(
'Different processes return ',
820 $
'different numbers of clusters' )
821 9984
FORMAT(
'Different processes return different clusters' )
822 9983
FORMAT(
'ICLUSTR not zero terminated' )
823 9982
FORMAT(
'IL, IU, VL or VU altered by PZHEEVR' )
824 9981
FORMAT(
'NZ altered by PZHEEVR with JOBZ=N' )