1 SUBROUTINE pdsepsubtst( 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,
15 CHARACTER JOBZ, RANGE, UPLO
16 INTEGER IA, IL, IPOSTPAD, IPREPAD, IU, JA, LIWORK,
17 $ LWORK, LWORK1, N, NOUT, RESULT
18 DOUBLE PRECISION ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
21 INTEGER DESCA( * ), ICLUSTR( * ), IFAIL( * ),
23 DOUBLE PRECISION A( * ), COPYA( * ), GAP( * ), WIN( * ),
24 $ WNEW( * ), WORK( * ), Z( * )
196 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
197 $ MB_, NB_, RSRC_, CSRC_, LLD_
198 PARAMETER ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
199 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
200 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
201 DOUBLE PRECISION PADVAL, FIVE, NEGONE
202 PARAMETER ( PADVAL = 13.5285d+0, five = 5.0d+0,
205 PARAMETER ( IPADVAL = 927 )
208 LOGICAL MISSLARGEST, MISSSMALLEST
209 INTEGER I, IAM, INDIWRK, INFO, ISIZESUBTST, ISIZESYEVX,
210 $ isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
211 $ minil, mq, mycol, myil, myrow, nclusters, np,
212 $ npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
213 $ sizechk, sizemqrleft, sizemqrright, sizeqrf,
214 $ sizeqtq, sizesubtst, sizesyevx, sizetms,
215 $ sizetst, valsize, vecsize
216 DOUBLE PRECISION EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
217 $ MINERROR, MINVL, NORMWIN, OLDVL, OLDVU, ORFAC,
221 INTEGER DESCZ( DLEN_ ), DSEED( 4 ), ITMP( 2 )
227 DOUBLE PRECISION PDLAMCH, PDLANSY
228 EXTERNAL LSAME, NUMROC, PDLAMCH, PDLANSY
231 EXTERNAL blacs_gridinfo,
descinit, dgamn2d, dgamx2d,
238 INTRINSIC abs,
max,
min, mod
242 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
244 CALL pdlasizesep( desca, iprepad, ipostpad, sizemqrleft,
245 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
246 $ sizechk, sizesyevx, isizesyevx, sizesubtst,
247 $ isizesubtst, sizetst, isizetst )
251 eps = pdlamch( desca( ctxt_ ),
'Eps' )
252 safmin = pdlamch( desca( ctxt_ ),
'Safe min' )
254 normwin = safmin / eps
256 $ normwin =
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
267 DO 10 i = 1, lwork1, 1
268 work( i+iprepad ) = 14.3d+0
270 DO 20 i = 1, liwork, 1
271 iwork( i+iprepad ) = 14
275 wnew( i+iprepad ) = 3.14159d+0
278 iclustr( 1+iprepad ) = 139
280 IF( lsame( jobz,
'N' ) )
THEN
283 IF( lsame( range,
'A' ) )
THEN
285 ELSE IF( lsame( range,
'I' ) )
THEN
286 maxeigs = iu - il + 1
288 minvl = vl - normwin*five*eps - abstol
289 maxvu = vu + normwin*five*eps + abstol
293 IF( win( i ).LT.minvl )
295 IF( win( i ).LE.maxvu )
299 maxeigs = maxiu - minil + 1
304 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
305 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
306 $ desca( ctxt_ ), desca( lld_ ), info )
308 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
309 indiwrk = 1 + iprepad + nprow*npcol + 1
312 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
318 IF( myrow.GE.nprow .OR. myrow.LT.0 )
329 $ dseed, win, maxsize, vecsize, valsize )
331 np = numroc( n, desca( mb_ ), myrow, 0, nprow )
332 nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
333 mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
335 CALL dlacpy(
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
338 CALL pdfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
341 CALL pdfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
342 $ ipostpad, padval+1.0d+0 )
344 CALL pdfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
347 CALL pdfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
348 $ iprepad, ipostpad, padval+3.0d+0 )
350 CALL pdfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
351 $ ipostpad, padval+4.0d+0 )
353 CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
354 $ ipostpad, ipadval )
356 CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
359 CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
360 $ 2*nprow*npcol, iprepad, ipostpad, ipadval )
366 DO 50 j = 1, maxeigs, 1
367 CALL pdelset( z( 1+iprepad ), i, j, desca, 13.0d+0 )
376 CALL pdsyevx( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
377 $ vl, vu, il, iu, abstol, m, nz, wnew( 1+iprepad ),
378 $ orfac, z( 1+iprepad ), ia, ja, desca,
379 $ work( 1+iprepad ), lwork1, iwork( 1+iprepad ),
380 $ liwork, ifail( 1+iprepad ), iclustr( 1+iprepad ),
381 $ gap( 1+iprepad ), info )
385 IF( thresh.LE.0 )
THEN
388 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVX-A', np, nq, a,
389 $ desca( lld_ ), iprepad, ipostpad, padval )
391 CALL pdchekpad( descz( ctxt_ ),
'PDSYEVX-Z', np, mq, z,
392 $ descz( lld_ ), iprepad, ipostpad,
395 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVX-WNEW', n, 1, wnew, n,
396 $ iprepad, ipostpad, padval+2.0d+0 )
398 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVX-GAP', nprow*npcol, 1,
399 $ gap, nprow*npcol, iprepad, ipostpad,
402 CALL pdchekpad( desca( ctxt_ ),
'PDSYEVX-WORK', lwork1, 1,
403 $ work, lwork1, iprepad, ipostpad,
406 CALL pichekpad( desca( ctxt_ ),
'PDSYEVX-IWORK', liwork, 1,
407 $ iwork, liwork, iprepad, ipostpad, ipadval )
409 CALL pichekpad( desca( ctxt_ ),
'PDSYEVX-IFAIL', n, 1, ifail,
410 $ n, iprepad, ipostpad, ipadval )
412 CALL pichekpad( desca( ctxt_ ),
'PDSYEVX-ICLUSTR',
413 $ 2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
414 $ iprepad, ipostpad, ipadval )
419 IF( lsame( range,
'A' ) )
THEN
421 $ dseed, wnew( 1+iprepad ), maxsize,
434 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
436 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1, 1,
440 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
442 $
WRITE( nout, fmt = * )
443 $
'Different processes return different INFO'
445 ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
448 $
WRITE( nout, fmt = 9999 )info
450 ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize )
THEN
452 $
WRITE( nout, fmt = 9996 )info
454 ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize )
THEN
456 $
WRITE( nout, fmt = 9996 )info
461 IF( lsame( jobz,
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
462 $ 0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) )
THEN
464 $
WRITE( nout, fmt = 9995 )
470 IF( ( m.LT.0 ) .OR. ( m.GT.n ) )
THEN
472 $
WRITE( nout, fmt = 9994 )
474 ELSE IF( lsame( range,
'A' ) .AND. ( m.NE.n ) )
THEN
476 $
WRITE( nout, fmt = 9993 )
478 ELSE IF( lsame( range,
'I' ) .AND. ( m.NE.iu-il+1 ) )
THEN
480 $
WRITE( nout, fmt = 9992 )
482 ELSE IF( lsame( jobz,
'V' ) .AND.
483 $ ( .NOT.( lsame( range,
'V' ) ) ) .AND. ( m.NE.nz ) )
486 $
WRITE( nout, fmt = 9991 )
492 IF( lsame( jobz,
'V' ) )
THEN
493 IF( lsame( range,
'V' ) )
THEN
496 $
WRITE( nout, fmt = 9990 )
499 IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 )
THEN
501 $
WRITE( nout, fmt = 9989 )
507 $
WRITE( nout, fmt = 9988 )
512 IF( result.EQ.0 )
THEN
519 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
521 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
524 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
526 $
WRITE( nout, fmt = 9987 )
533 work( i ) = wnew( i+iprepad )
534 work( i+m ) = wnew( i+iprepad )
537 CALL dgamn2d( desca( ctxt_ ),
'a',
' ', m, 1, work, m, 1,
539 CALL dgamx2d( desca( ctxt_ ),
'a',
' ', m, 1,
540 $ work( 1+m ), m, 1, 1, -1, -1, 0 )
544 IF( result.EQ.0 .AND. ( abs( work( i )-work( m+
545 $ i ) ).GT.five*eps*abs( work( i ) ) ) )
THEN
547 $
WRITE( nout, fmt = 9986 )
556 IF( lsame( jobz,
'V' ) )
THEN
558 DO 90 i = 0, nprow*npcol - 1
559 IF( iclustr( 1+iprepad+2*i ).EQ.0 )
561 nclusters = nclusters + 1
564 itmp( 1 ) = nclusters
565 itmp( 2 ) = nclusters
567 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
569 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
572 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
574 $
WRITE( nout, fmt = 9985 )
580 DO 110 i = 1, nclusters
581 iwork( indiwrk+i ) = iclustr( i+iprepad )
582 iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
584 CALL igamn2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
585 $ iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
587 CALL igamx2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
588 $ iwork( indiwrk+1+nclusters ),
589 $ nclusters*2+1, 1, 1, -1, -1, 0 )
592 DO 120 i = 1, nclusters
593 IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
594 $ iwork( indiwrk+nclusters+i ) )
THEN
596 $
WRITE( nout, fmt = 9984 )
601 IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 )
THEN
603 $
WRITE( nout, fmt = 9983 )
610 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1,
620 epsnorma = pdlansy(
'I', uplo, n, copya, ia, ja, desca,
634 IF( lsame( jobz,
'V' ) )
THEN
638 CALL pdfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
639 $ iprepad, ipostpad, 4.3d+0 )
641 CALL pdsepchk( n, nz, copya, ia, ja, desca,
642 $
max( abstol+epsnorma, safmin ), thresh,
643 $ z( 1+iprepad ), ia, ja, descz,
644 $ a( 1+iprepad ), ia, ja, desca,
645 $ wnew( 1+iprepad ), work( 1+iprepad ),
646 $ sizechk, tstnrm, res )
648 CALL pdchekpad( desca( ctxt_ ),
'PDSEPCHK-WORK', sizechk, 1,
649 $ work, sizechk, iprepad, ipostpad, 4.3d+0 )
656 CALL pdfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
657 $ iprepad, ipostpad, 4.3d+0 )
660 CALL pdsepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
661 $ a( 1+iprepad ), ia, ja, desca,
662 $ iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
663 $ gap( 1+iprepad ), work( iprepad+1 ), sizeqtq,
664 $ qtqnrm, info, res )
666 CALL pdchekpad( desca( ctxt_ ),
'PDSEPQTQ-WORK', sizeqtq, 1,
667 $ work, sizeqtq, iprepad, ipostpad, 4.3d+0 )
674 $
WRITE( nout, fmt = 9998 )info
687 IF( lsame( range,
'V' ) )
THEN
692 IF( lsame( range,
'A' ) )
THEN
704 DO 140 myil = minil, maxil
709 misssmallest = .true.
710 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.1 ) )
711 $ misssmallest = .false.
712 IF( misssmallest .AND. ( win( myil-1 ).LT.vl+normwin*
713 $ five*thresh*eps ) )misssmallest = .false.
715 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.maxil ) )
716 $ misslargest = .false.
717 IF( misslargest .AND. ( win( myil+m ).GT.vu-normwin*five*
718 $ thresh*eps ) )misslargest = .false.
719 IF( .NOT.misssmallest )
THEN
720 IF( .NOT.misslargest )
THEN
725 error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
726 maxerror =
max( maxerror, error )
729 minerror =
min( maxerror, minerror )
740 IF( lsame( jobz,
'V' ) .AND. lsame( range,
'A' ) )
THEN
741 IF( minerror.GT.normwin*five*five*thresh*eps )
THEN
743 $
WRITE( nout, fmt = 9997 )minerror, normwin
747 IF( minerror.GT.normwin*five*thresh*eps )
THEN
749 $
WRITE( nout, fmt = 9997 )minerror, normwin
758 IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
761 $
WRITE( nout, fmt = 9982 )
765 IF( lsame( jobz,
'N' ) .AND. ( nz.NE.oldnz ) )
THEN
767 $
WRITE( nout, fmt = 9981 )
775 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1, -1,
783 9999
FORMAT(
'PDSYEVX returned INFO=', i7 )
784 9998
FORMAT(
'PDSEPQTQ returned INFO=', i7 )
785 9997
FORMAT(
'PDSEPSUBTST minerror =', d11.2,
' normwin=', d11.2 )
786 9996
FORMAT(
'PDSYEVX returned INFO=', i7,
787 $
' despite adequate workspace' )
788 9995
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
789 9994
FORMAT(
'M not in the range 0 to N' )
790 9993
FORMAT(
'M not equal to N' )
791 9992
FORMAT(
'M not equal to IU-IL+1' )
792 9991
FORMAT(
'M not equal to NZ' )
793 9990
FORMAT(
'NZ > M' )
794 9989
FORMAT(
'NZ < M' )
795 9988
FORMAT(
'NZ not equal to M' )
796 9987
FORMAT(
'Different processes return different values for M' )
797 9986
FORMAT(
'Different processes return different eigenvalues' )
798 9985
FORMAT(
'Different processes return ',
799 $
'different numbers of clusters' )
800 9984
FORMAT(
'Different processes return different clusters' )
801 9983
FORMAT(
'ICLUSTR not zero terminated' )
802 9982
FORMAT(
'IL, IU, VL or VU altered by PDSYEVX' )
803 9981
FORMAT(
'NZ altered by PDSYEVX with JOBZ=N' )