1 SUBROUTINE psseprsubtst( 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, LWORK1,
5 $ IWORK, LIWORK, RESULT, TSTNRM, QTQNRM,
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
23 INTEGER DESCA( * ), ICLUSTR( * ), IFAIL( * ),
25 REAL A( * ), COPYA( * ), GAP( * ), WIN( * ),
26 $ WNEW( * ), WORK( * ), Z( * )
187 INTEGER DLEN_, CTXT_, M_, N_,
188 $ MB_, NB_, RSRC_, CSRC_, LLD_
189 PARAMETER ( DLEN_ = 9,
190 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
191 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
192 REAL PADVAL, FIVE, NEGONE
193 PARAMETER ( PADVAL = 13.5285e0, five = 5.0e0,
196 PARAMETER ( IPADVAL = 927 )
199 LOGICAL MISSLARGEST, MISSSMALLEST
200 INTEGER I, IAM, INDIWRK, INFO, ISIZESUBTST, ISIZEEVR,
201 $ isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
202 $ minil, mq, mycol, myil, myrow, nclusters, np,
203 $ npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
204 $ sizechk, sizemqrleft, sizemqrright, sizeqrf,
205 $ sizeqtq, sizesubtst, sizeevr, sizetms,
206 $ sizetst, valsize, vecsize
207 REAL EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
208 $ MINERROR, MINVL, NORMWIN, OLDVL, OLDVU,
212 INTEGER DESCZ( DLEN_ ), ISEED( 4 ), ITMP( 2 )
218 REAL PSLAMCH, PSLANSY
219 EXTERNAL LSAME, NUMROC, PSLAMCH, PSLANSY
222 EXTERNAL blacs_gridinfo,
descinit, igamn2d, igamx2d,
229 INTRINSIC abs,
max,
min, mod
233 CALL pslasizesepr( desca, iprepad, ipostpad, sizemqrleft,
234 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
235 $ sizechk, sizeevr, isizeevr, sizesubtst,
236 $ isizesubtst, sizetst, isizetst )
240 eps = pslamch( desca( ctxt_ ),
'Eps' )
241 safmin = pslamch( desca( ctxt_ ),
'Safe min' )
243 normwin = safmin / eps
245 $ normwin =
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
256 DO 10 i = 1, lwork1, 1
257 work( i+iprepad ) = 14.3e0
260 DO 20 i = 1, liwork, 1
261 iwork( i+iprepad ) = 14
265 wnew( i+iprepad ) = 3.14159e0
268 iclustr( 1+iprepad ) = 139
270 IF (lsame( range,
'V' ) )
THEN
274 IF( lsame( jobz,
'N' ) )
THEN
277 IF( lsame( range,
'A' ) )
THEN
279 ELSE IF( lsame( range,
'I' ) )
THEN
280 maxeigs = iu - il + 1
282 minvl = vl - normwin*five*eps - abstol
283 maxvu = vu + normwin*five*eps + abstol
289 IF( win( i ).LT.minvl )
291 IF( win( i ).LE.maxvu )
295 maxeigs = maxiu - minil + 1
300 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
301 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
302 $ desca( ctxt_ ), desca( lld_ ), info )
304 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
305 indiwrk = 1 + iprepad + nprow*npcol + 1
308 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
314 IF( myrow.GE.nprow .OR. myrow.LT.0 )
321 $ iseed, win, maxsize, vecsize, valsize )
323 np = numroc( n, desca( mb_ ), myrow, 0, nprow )
324 nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
325 mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
327 CALL slacpy(
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
330 CALL psfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
333 CALL psfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
334 $ ipostpad, padval+1.0e0 )
342 CALL psfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
345 CALL psfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
346 $ iprepad, ipostpad, padval+3.0e0 )
348 CALL psfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
349 $ ipostpad, padval+4.0e0 )
351 CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
352 $ ipostpad, ipadval )
354 CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
357 CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
358 $ 2*nprow*npcol, iprepad, ipostpad, ipadval )
364 DO 50 j = 1, maxeigs, 1
365 CALL pselset( z( 1+iprepad ), i, j, desca, 13.0e0 )
379 CALL pssyevr( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
380 $ vl, vu, il, iu, m, nz, wnew( 1+iprepad ),
381 $ z( 1+iprepad ), ia, ja, desca,
382 $ work( 1+iprepad ), lwork1, iwork( 1+iprepad ),
396 iclustr( 1+iprepad ) = 0
398 IF( thresh.LE.0 )
THEN
401 CALL pschekpad( desca( ctxt_ ),
'PSSYEVR-A', np, nq, a,
402 $ desca( lld_ ), iprepad, ipostpad, padval )
404 CALL pschekpad( descz( ctxt_ ),
'PSSYEVR-Z', np, mq, z,
405 $ descz( lld_ ), iprepad, ipostpad,
408 CALL pschekpad( desca( ctxt_ ),
'PSSYEVR-WNEW', n, 1, wnew, n,
409 $ iprepad, ipostpad, padval+2.0e0 )
411 CALL pschekpad( desca( ctxt_ ),
'PSSYEVR-GAP', nprow*npcol, 1,
412 $ gap, nprow*npcol, iprepad, ipostpad,
415 CALL pschekpad( desca( ctxt_ ),
'PSSYEVR-WORK', lwork1, 1,
416 $ work, lwork1, iprepad, ipostpad,
419 CALL pichekpad( desca( ctxt_ ),
'PSSYEVR-IWORK', liwork, 1,
420 $ iwork, liwork, iprepad, ipostpad, ipadval )
422 CALL pichekpad( desca( ctxt_ ),
'PSSYEVR-IFAIL', n, 1, ifail,
423 $ n, iprepad, ipostpad, ipadval )
425 CALL pichekpad( desca( ctxt_ ),
'PSSYEVR-ICLUSTR',
426 $ 2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
427 $ iprepad, ipostpad, ipadval )
431 IF( lsame( range,
'A' ) )
THEN
433 $ iseed, wnew( 1+iprepad ), maxsize,
443 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
445 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1, 1,
449 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
451 $
WRITE( nout, fmt = * )
452 $
'Different processes return different INFO'
454 ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
457 $
WRITE( nout, fmt = 9999 )info
459 ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize )
THEN
461 $
WRITE( nout, fmt = 9996 )info
463 ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize )
THEN
465 $
WRITE( nout, fmt = 9996 )info
469 IF( lsame( jobz,
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
470 $ 0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) )
THEN
472 $
WRITE( nout, fmt = 9995 )
478 IF( ( m.LT.0 ) .OR. ( m.GT.n ) )
THEN
480 $
WRITE( nout, fmt = 9994 )
481 WRITE( nout,*)
'M = ', m,
'\n',
'N = ', n
483 ELSE IF( lsame( range,
'A' ) .AND. ( m.NE.n ) )
THEN
485 $
WRITE( nout, fmt = 9993 )
487 ELSE IF( lsame( range,
'I' ) .AND. ( m.NE.iu-il+1 ) )
THEN
489 WRITE( nout, fmt = 9992 )
490 WRITE( nout,*)
'IL = ', il,
' IU = ', iu,
' M = ', m
493 ELSE IF( lsame( jobz,
'V' ) .AND.
494 $ ( .NOT.( lsame( range,
'V' ) ) ) .AND. ( m.NE.nz ) )
497 $
WRITE( nout, fmt = 9991 )
503 IF( lsame( jobz,
'V' ) )
THEN
504 IF( lsame( range,
'V' ) )
THEN
507 $
WRITE( nout, fmt = 9990 )
510 IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 )
THEN
512 $
WRITE( nout, fmt = 9989 )
518 $
WRITE( nout, fmt = 9988 )
523 IF( result.EQ.0 )
THEN
530 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
532 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
535 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
537 $
WRITE( nout, fmt = 9987 )
544 work( i ) = wnew( i+iprepad )
545 work( i+m ) = wnew( i+iprepad )
548 CALL sgamn2d( desca( ctxt_ ),
'a',
' ', m, 1, work, m, 1,
550 CALL sgamx2d( desca( ctxt_ ),
'a',
' ', m, 1,
551 $ work( 1+m ), m, 1, 1, -1, -1, 0 )
554 IF( result.EQ.0 .AND. ( abs( work( i )-work( m+
555 $ i ) ).GT.five*eps*abs( work( i ) ) ) )
THEN
557 $
WRITE( nout, fmt = 9986 )
566 IF( lsame( jobz,
'V' ) )
THEN
568 DO 90 i = 0, nprow*npcol - 1
569 IF( iclustr( 1+iprepad+2*i ).EQ.0 )
571 nclusters = nclusters + 1
574 itmp( 1 ) = nclusters
575 itmp( 2 ) = nclusters
577 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
579 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
582 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
584 $
WRITE( nout, fmt = 9985 )
590 DO 110 i = 1, nclusters
591 iwork( indiwrk+i ) = iclustr( i+iprepad )
592 iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
594 CALL igamn2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
595 $ iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
597 CALL igamx2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
598 $ iwork( indiwrk+1+nclusters ),
599 $ nclusters*2+1, 1, 1, -1, -1, 0 )
601 DO 120 i = 1, nclusters
602 IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
603 $ iwork( indiwrk+nclusters+i ) )
THEN
605 $
WRITE( nout, fmt = 9984 )
610 IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 )
THEN
612 $
WRITE( nout, fmt = 9983 )
618 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1,
628 epsnorma = pslansy(
'I', uplo, n, copya, ia, ja, desca,
632 IF( lsame( jobz,
'V' ) )
THEN
636 CALL psfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
637 $ iprepad, ipostpad, 4.3e0 )
639 CALL pssepchk( n, nz, copya, ia, ja, desca,
640 $
max( abstol+epsnorma, safmin ), thresh,
641 $ z( 1+iprepad ), ia, ja, descz,
642 $ a( 1+iprepad ), ia, ja, desca,
643 $ wnew( 1+iprepad ), work( 1+iprepad ),
644 $ sizechk, tstnrm, res )
646 CALL pschekpad( desca( ctxt_ ),
'PSSEPCHK-WORK', sizechk, 1,
647 $ work, sizechk, iprepad, ipostpad, 4.3e0 )
654 CALL psfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
655 $ iprepad, ipostpad, 4.3e0 )
658 CALL pssepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
659 $ a( 1+iprepad ), ia, ja, desca,
660 $ iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
661 $ gap( 1+iprepad ), work( iprepad+1 ), sizeqtq,
662 $ qtqnrm, info, res )
664 CALL pschekpad( desca( ctxt_ ),
'PSSEPQTQ-WORK', sizeqtq, 1,
665 $ work, sizeqtq, iprepad, ipostpad, 4.3e0 )
672 $
WRITE( nout, fmt = 9998 )info
683 IF( lsame( range,
'V' ) )
THEN
688 IF( lsame( range,
'A' ) )
THEN
700 DO 140 myil = minil, maxil
705 misssmallest = .true.
706 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.1 ) )
707 $ misssmallest = .false.
708 IF( misssmallest .AND. ( win( myil-1 ).LT.vl+normwin*
709 $ five*thresh*eps ) )misssmallest = .false.
711 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.maxil ) )
712 $ misslargest = .false.
713 IF( misslargest .AND. ( win( myil+m ).GT.vu-normwin*five*
714 $ thresh*eps ) )misslargest = .false.
715 IF( .NOT.misssmallest )
THEN
716 IF( .NOT.misslargest )
THEN
723 error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
724 maxerror =
max( maxerror, error )
727 minerror =
min( maxerror, minerror )
737 IF( lsame( jobz,
'V' ) .AND. lsame( range,
'A' ) )
THEN
738 IF( minerror.GT.normwin*five*five*thresh*eps )
THEN
740 $
WRITE( nout, fmt = 9997 )minerror, normwin
744 IF( minerror.GT.normwin*five*thresh*eps )
THEN
746 $
WRITE( nout, fmt = 9997 )minerror, normwin
754 IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
757 $
WRITE( nout, fmt = 9982 )
761 IF( lsame( jobz,
'N' ) .AND. ( nz.NE.oldnz ) )
THEN
763 $
WRITE( nout, fmt = 9981 )
771 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1, -1,
778 9999
FORMAT(
'PSSYEVR returned INFO=', i7 )
779 9998
FORMAT(
'PSSEPQTQ returned INFO=', i7 )
780 9997
FORMAT(
'PSSEPRSUBTST minerror =', d11.2,
' normwin=', d11.2 )
781 9996
FORMAT(
'PSSYEVR returned INFO=', i7,
782 $
' despite adequate workspace' )
783 9995
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
784 9994
FORMAT(
'M not in the range 0 to N' )
785 9993
FORMAT(
'M not equal to N' )
786 9992
FORMAT(
'M not equal to IU-IL+1' )
787 9991
FORMAT(
'M not equal to NZ' )
788 9990
FORMAT(
'NZ > M' )
789 9989
FORMAT(
'NZ < M' )
790 9988
FORMAT(
'NZ not equal to M' )
791 9987
FORMAT(
'Different processes return different values for M' )
792 9986
FORMAT(
'Different processes return different eigenvalues' )
793 9985
FORMAT(
'Different processes return ',
794 $
'different numbers of clusters' )
795 9984
FORMAT(
'Different processes return different clusters' )
796 9983
FORMAT(
'ICLUSTR not zero terminated' )
797 9982
FORMAT(
'IL, IU, VL or VU altered by PSSYEVR' )
798 9981
FORMAT(
'NZ altered by PSSYEVR with JOBZ=N' )