1 SUBROUTINE pcseprsubtst( 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 REAL ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
24 INTEGER DESCA( * ), ICLUSTR( * ), IFAIL( * ),
26 COMPLEX A( * ), COPYA( * ), WORK( * ), Z( * )
27 REAL 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 REAL PADVAL, FIVE, NEGONE
201 PARAMETER ( PADVAL = 13.5285e0, five = 5.0e0,
204 PARAMETER ( ZPADVAL = ( 13.989e0, 1.93e0 ) )
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 REAL EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
219 $ MINERROR, MINVL, NORMWIN, OLDVL, OLDVU,
223 INTEGER DESCZ( DLEN_ ), ISEED( 4 ), ITMP( 2 )
229 REAL PSLAMCH, PCLANHE
230 EXTERNAL LSAME, NUMROC, PSLAMCH, PCLANHE
233 EXTERNAL blacs_gridinfo, clacpy,
descinit, igamn2d,
240 INTRINSIC abs,
max,
min, mod
244 CALL pclasizesepr( desca, iprepad, ipostpad, sizemqrleft,
245 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
246 $ sizechk, sizeevr, rsizeevr, isizeevr,
247 $ sizesubtst, rsizesubtst, isizesubtst,
248 $ sizetst, rsizetst, isizetst )
252 eps = pslamch( desca( ctxt_ ),
'Eps' )
253 safmin = pslamch( desca( ctxt_ ),
'Safe min' )
255 normwin = safmin / eps
257 $ normwin =
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
268 DO 10 i = 1, lwork1, 1
269 rwork( i+iprepad ) = 14.3e0
272 DO 15 i = 1, lwork, 1
273 work( i+iprepad ) = ( 15.63e0, 1.1e0 )
276 DO 20 i = 1, liwork, 1
277 iwork( i+iprepad ) = 14
281 wnew( i+iprepad ) = 3.14159e0
284 iclustr( 1+iprepad ) = 139
286 IF (lsame( range,
'V' ) )
THEN
290 IF( lsame( jobz,
'N' ) )
THEN
293 IF( lsame( range,
'A' ) )
THEN
295 ELSE IF( lsame( range,
'I' ) )
THEN
296 maxeigs = iu - il + 1
298 minvl = vl - normwin*five*eps - abstol
299 maxvu = vu + normwin*five*eps + abstol
305 IF( win( i ).LT.minvl )
307 IF( win( i ).LE.maxvu )
311 maxeigs = maxiu - minil + 1
316 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
317 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
318 $ desca( ctxt_ ), desca( lld_ ), info )
320 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
321 indiwrk = 1 + iprepad + nprow*npcol + 1
324 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
330 IF( myrow.GE.nprow .OR. myrow.LT.0 )
337 $ iseed, win, maxsize, vecsize, valsize )
339 np = numroc( n, desca( mb_ ), myrow, 0, nprow )
340 nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
341 mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
343 CALL clacpy(
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
346 CALL pcfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
347 $ ipostpad, zpadval )
349 CALL pcfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
350 $ ipostpad, zpadval+1.0e0 )
358 CALL psfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
361 CALL psfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
362 $ iprepad, ipostpad, padval+3.0e0 )
364 CALL psfillpad( desca( ctxt_ ), lwork1, 1, rwork,lwork1, iprepad,
365 $ ipostpad, padval+4.0e0 )
367 CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
368 $ ipostpad, ipadval )
370 CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
373 CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
374 $ 2*nprow*npcol, iprepad, ipostpad, ipadval )
376 CALL pcfillpad( desca( ctxt_ ), lwork, 1, work, lwork, iprepad,
377 $ ipostpad, zpadval+4.1e0 )
383 DO 50 j = 1, maxeigs, 1
384 CALL pcelset( z( 1+iprepad ), i, j, desca,
385 $ ( 13.0e0, 1.34e0 ) )
399 CALL pcheevr( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
400 $ vl, vu, il, iu, m, nz, wnew( 1+iprepad ),
401 $ z( 1+iprepad ), ia, ja, desca,
402 $ work( 1+iprepad ), sizeevr,
403 $ rwork( 1+iprepad ), lwork1,
404 $ iwork( 1+iprepad ), liwork, info )
417 iclustr( 1+iprepad ) = 0
419 IF( thresh.LE.0 )
THEN
422 CALL pcchekpad( desca( ctxt_ ),
'PCHEEVR-A', np, nq, a,
423 $ desca( lld_ ), iprepad, ipostpad, zpadval )
425 CALL pcchekpad( descz( ctxt_ ),
'PCHEEVR-Z', np, mq, z,
426 $ descz( lld_ ), iprepad, ipostpad,
429 CALL pschekpad( desca( ctxt_ ),
'PCHEEVR-WNEW', n, 1, wnew, n,
430 $ iprepad, ipostpad, padval+2.0e0 )
432 CALL pschekpad( desca( ctxt_ ),
'PCHEEVR-GAP', nprow*npcol, 1,
433 $ gap, nprow*npcol, iprepad, ipostpad,
436 CALL pschekpad( desca( ctxt_ ),
'PCHEEVR-RWORK',lwork1, 1,
437 $ rwork, lwork1, iprepad, ipostpad,
440 CALL pcchekpad( desca( ctxt_ ),
'PCHEEVR-WORK',lwork, 1,
441 $ work, lwork, iprepad, ipostpad,
444 CALL pichekpad( desca( ctxt_ ),
'PCHEEVR-IWORK', liwork, 1,
445 $ iwork, liwork, iprepad, ipostpad, ipadval )
447 CALL pichekpad( desca( ctxt_ ),
'PCHEEVR-IFAIL', n, 1, ifail,
448 $ n, iprepad, ipostpad, ipadval )
450 CALL pichekpad( desca( ctxt_ ),
'PCHEEVR-ICLUSTR',
451 $ 2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
452 $ iprepad, ipostpad, ipadval )
456 IF( lsame( range,
'A' ) )
THEN
458 $ iseed, wnew( 1+iprepad ), maxsize,
468 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
470 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1, 1,
474 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
476 $
WRITE( nout, fmt = * )
477 $
'Different processes return different INFO'
479 ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
482 $
WRITE( nout, fmt = 9999 )info
484 ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize )
THEN
486 $
WRITE( nout, fmt = 9996 )info
488 ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize )
THEN
490 $
WRITE( nout, fmt = 9996 )info
494 IF( lsame( jobz,
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
495 $ 0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) )
THEN
497 $
WRITE( nout, fmt = 9995 )
503 IF( ( m.LT.0 ) .OR. ( m.GT.n ) )
THEN
505 $
WRITE( nout, fmt = 9994 )
506 WRITE( nout,*)
'M = ', m,
'\n',
'N = ', n
508 ELSE IF( lsame( range,
'A' ) .AND. ( m.NE.n ) )
THEN
510 $
WRITE( nout, fmt = 9993 )
512 ELSE IF( lsame( range,
'I' ) .AND. ( m.NE.iu-il+1 ) )
THEN
514 WRITE( nout, fmt = 9992 )
515 WRITE( nout,*)
'IL = ', il,
' IU = ', iu,
' M = ', m
518 ELSE IF( lsame( jobz,
'V' ) .AND.
519 $ ( .NOT.( lsame( range,
'V' ) ) ) .AND. ( m.NE.nz ) )
522 $
WRITE( nout, fmt = 9991 )
528 IF( lsame( jobz,
'V' ) )
THEN
529 IF( lsame( range,
'V' ) )
THEN
532 $
WRITE( nout, fmt = 9990 )
535 IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 )
THEN
537 $
WRITE( nout, fmt = 9989 )
543 $
WRITE( nout, fmt = 9988 )
548 IF( result.EQ.0 )
THEN
555 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
557 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
560 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
562 $
WRITE( nout, fmt = 9987 )
569 rwork( i ) = wnew( i+iprepad )
570 rwork( i+m ) = wnew( i+iprepad )
573 CALL sgamn2d( desca( ctxt_ ),
'a',
' ', m, 1, rwork, m,
575 CALL sgamx2d( desca( ctxt_ ),
'a',
' ', m, 1,
576 $ rwork( 1+m ), m, 1, 1, -1, -1, 0 )
579 IF( result.EQ.0 .AND. ( abs( rwork( i )-rwork( m+
580 $ i ) ).GT.five*eps*abs( rwork( i ) ) ) )
THEN
582 $
WRITE( nout, fmt = 9986 )
591 IF( lsame( jobz,
'V' ) )
THEN
593 DO 90 i = 0, nprow*npcol - 1
594 IF( iclustr( 1+iprepad+2*i ).EQ.0 )
596 nclusters = nclusters + 1
599 itmp( 1 ) = nclusters
600 itmp( 2 ) = nclusters
602 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
604 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
607 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
609 $
WRITE( nout, fmt = 9985 )
615 DO 110 i = 1, nclusters
616 iwork( indiwrk+i ) = iclustr( i+iprepad )
617 iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
619 CALL igamn2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
620 $ iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
622 CALL igamx2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
623 $ iwork( indiwrk+1+nclusters ),
624 $ nclusters*2+1, 1, 1, -1, -1, 0 )
626 DO 120 i = 1, nclusters
627 IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
628 $ iwork( indiwrk+nclusters+i ) )
THEN
630 $
WRITE( nout, fmt = 9984 )
635 IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 )
THEN
637 $
WRITE( nout, fmt = 9983 )
643 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1,
653 epsnorma = pclanhe(
'I', uplo, n, copya, ia, ja, desca,
657 IF( lsame( jobz,
'V' ) )
THEN
661 CALL psfillpad( desca( ctxt_ ), sizechk, 1, rwork,sizechk,
662 $ iprepad, ipostpad, 4.3e0 )
664 CALL pcsepchk( n, nz, copya, ia, ja, desca,
665 $
max( abstol+epsnorma, safmin ), thresh,
666 $ z( 1+iprepad ), ia, ja, descz,
667 $ a( 1+iprepad ), ia, ja, desca,
668 $ wnew( 1+iprepad ), rwork( 1+iprepad ),
669 $ sizechk, tstnrm, res )
671 CALL pschekpad( desca( ctxt_ ),
'PCSEPCHK-RWORK',sizechk, 1,
672 $ rwork,sizechk, iprepad, ipostpad, 4.3e0 )
679 CALL psfillpad( desca( ctxt_ ), sizeqtq, 1,rwork, sizeqtq,
680 $ iprepad, ipostpad, 4.3e0 )
683 CALL pcsepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
684 $ a( 1+iprepad ), ia, ja, desca,
685 $ iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
686 $ gap( 1+iprepad ),rwork( iprepad+1 ), sizeqtq,
687 $ qtqnrm, info, res )
689 CALL pschekpad( desca( ctxt_ ),
'PSSEPQTQ-RWORK',sizeqtq, 1,
690 $ rwork,sizeqtq, iprepad, ipostpad, 4.3e0 )
697 $
WRITE( nout, fmt = 9998 )info
708 IF( lsame( range,
'V' ) )
THEN
713 IF( lsame( range,
'A' ) )
THEN
725 DO 140 myil = minil, maxil
730 misssmallest = .true.
731 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.1 ) )
732 $ misssmallest = .false.
733 IF( misssmallest .AND. ( win( myil-1 ).LT.vl+normwin*
734 $ five*thresh*eps ) )misssmallest = .false.
736 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.maxil ) )
737 $ misslargest = .false.
738 IF( misslargest .AND. ( win( myil+m ).GT.vu-normwin*five*
739 $ thresh*eps ) )misslargest = .false.
740 IF( .NOT.misssmallest )
THEN
741 IF( .NOT.misslargest )
THEN
748 error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
749 maxerror =
max( maxerror, error )
752 minerror =
min( maxerror, minerror )
762 IF( lsame( jobz,
'V' ) .AND. lsame( range,
'A' ) )
THEN
763 IF( minerror.GT.normwin*five*five*thresh*eps )
THEN
765 $
WRITE( nout, fmt = 9997 )minerror, normwin
769 IF( minerror.GT.normwin*five*thresh*eps )
THEN
771 $
WRITE( nout, fmt = 9997 )minerror, normwin
779 IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
782 $
WRITE( nout, fmt = 9982 )
786 IF( lsame( jobz,
'N' ) .AND. ( nz.NE.oldnz ) )
THEN
788 $
WRITE( nout, fmt = 9981 )
796 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1, -1,
803 9999
FORMAT(
'PCHEEVR returned INFO=', i7 )
804 9998
FORMAT(
'PCSEPQTQ returned INFO=', i7 )
805 9997
FORMAT(
'PCSEPRSUBTST minerror =', d11.2,
' normwin=', d11.2 )
806 9996
FORMAT(
'PCHEEVR returned INFO=', i7,
807 $
' despite adequate workspace' )
808 9995
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
809 9994
FORMAT(
'M not in the range 0 to N' )
810 9993
FORMAT(
'M not equal to N' )
811 9992
FORMAT(
'M not equal to IU-IL+1' )
812 9991
FORMAT(
'M not equal to NZ' )
813 9990
FORMAT(
'NZ > M' )
814 9989
FORMAT(
'NZ < M' )
815 9988
FORMAT(
'NZ not equal to M' )
816 9987
FORMAT(
'Different processes return different values for M' )
817 9986
FORMAT(
'Different processes return different eigenvalues' )
818 9985
FORMAT(
'Different processes return ',
819 $
'different numbers of clusters' )
820 9984
FORMAT(
'Different processes return different clusters' )
821 9983
FORMAT(
'ICLUSTR not zero terminated' )
822 9982
FORMAT(
'IL, IU, VL or VU altered by PCHEEVR' )
823 9981
FORMAT(
'NZ altered by PCHEEVR with JOBZ=N' )