3 SUBROUTINE pcsepsubtst( WKNOWN, JOBZ, RANGE, UPLO, N, VL, VU, IL,
4 $ IU, THRESH, ABSTOL, A, COPYA, Z, IA, JA,
5 $ DESCA, WIN, WNEW, IFAIL, ICLUSTR, GAP,
6 $ IPREPAD, IPOSTPAD, WORK, LWORK, RWORK,
7 $ LRWORK, LWORK1, IWORK, LIWORK, RESULT,
8 $ TSTNRM, QTQNRM, NOUT )
17 CHARACTER JOBZ, RANGE, UPLO
18 INTEGER IA, IL, IPOSTPAD, IPREPAD, IU, JA, LIWORK,
19 $ LRWORK, LWORK, LWORK1, N, NOUT, RESULT
20 REAL ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
23 INTEGER DESCA( * ), ICLUSTR( * ), IFAIL( * ),
25 REAL GAP( * ), RWORK( * ), WIN( * ), WNEW( * )
26 COMPLEX A( * ), COPYA( * ), WORK( * ), Z( * )
204 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
205 $ MB_, NB_, RSRC_, CSRC_, LLD_
206 PARAMETER ( BLOCK_CYCLIC_2D = 1, dlen_ = 9, dtype_ = 1,
207 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
208 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
209 REAL PADVAL, FIVE, NEGONE
210 PARAMETER ( PADVAL = 13.5285e+0, five = 5.0e+0,
213 PARAMETER ( CPADVAL = ( 13.989e+0, 1.93e+0 ) )
215 parameter( ipadval = 927 )
218 LOGICAL MISSLARGEST, MISSSMALLEST
219 INTEGER I, IAM, INDIWRK, INFO, ISIZEHEEVX, ISIZESUBTST,
220 $ isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
221 $ minil, mq, mycol, myil, myrow, nclusters, np,
222 $ npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
223 $ rsizechk, rsizeheevx, rsizeqtq, rsizesubtst,
224 $ rsizetst, sizeheevx, sizemqrleft, sizemqrright,
225 $ sizeqrf, sizesubtst, sizetms, sizetst, valsize,
226 $ vecsize, sizeheevd, rsizeheevd, isizeheevd
227 REAL EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
228 $ MINERROR, MINVL, NORMWIN, OLDVL, OLDVU, ORFAC,
232 INTEGER DESCZ( DLEN_ ), DSEED( 4 ), ITMP( 2 )
238 REAL PCLANHE, PSLAMCH
239 EXTERNAL LSAME, NUMROC, PCLANHE, PSLAMCH
242 EXTERNAL blacs_gridinfo, clacpy,
descinit, igamn2d,
249 INTRINSIC abs,
max,
min, mod
253 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
255 CALL pclasizesep( desca, iprepad, ipostpad, sizemqrleft,
256 $ sizemqrright, sizeqrf, sizetms, rsizeqtq,
257 $ rsizechk, sizeheevx, rsizeheevx, isizeheevx,
258 $ sizeheevd, rsizeheevd, isizeheevd,
259 $ sizesubtst, rsizesubtst, isizesubtst, sizetst,
260 $ rsizetst, isizetst )
264 eps = pslamch( desca( ctxt_ ),
'Eps' )
265 safmin = pslamch( desca( ctxt_ ),
'Safe min' )
267 normwin = safmin / eps
269 $ normwin =
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
280 DO 10 i = 1, lwork1, 1
281 rwork( i+iprepad ) = 14.3e+0
283 DO 20 i = 1, liwork, 1
284 iwork( i+iprepad ) = 14
286 DO 30 i = 1, lwork, 1
287 work( i+iprepad ) = ( 15.63e+0, 1.1e+0 )
291 wnew( i+iprepad ) = 3.14159e+0
294 iclustr( 1+iprepad ) = 139
296 IF( lsame( jobz,
'N' ) )
THEN
299 IF( lsame( range,
'A' ) )
THEN
301 ELSE IF( lsame( range,
'I' ) )
THEN
302 maxeigs = iu - il + 1
304 minvl = vl - normwin*five*eps - abstol
305 maxvu = vu + normwin*five*eps + abstol
309 IF( win( i ).LT.minvl )
311 IF( win( i ).LE.maxvu )
315 maxeigs = maxiu - minil + 1
320 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
321 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
322 $ desca( ctxt_ ), desca( lld_ ), info )
324 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
325 indiwrk = 1 + iprepad + nprow*npcol + 1
328 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
334 IF( myrow.GE.nprow .OR. myrow.LT.0 )
345 $ dseed, win, maxsize, vecsize, valsize )
347 np = numroc( n, desca( mb_ ), myrow, 0, nprow )
348 nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
349 mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
351 CALL clacpy(
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
354 CALL pcfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
355 $ ipostpad, cpadval )
357 CALL pcfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
358 $ ipostpad, cpadval+1.0e+0 )
360 CALL psfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
363 CALL psfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
364 $ iprepad, ipostpad, padval+3.0e+0 )
366 CALL psfillpad( desca( ctxt_ ), lwork1, 1, rwork, lwork1, iprepad,
367 $ ipostpad, padval+4.0e+0 )
369 CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
370 $ ipostpad, ipadval )
372 CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
375 CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
376 $ 2*nprow*npcol, iprepad, ipostpad, ipadval )
378 CALL pcfillpad( desca( ctxt_ ), lwork, 1, work, lwork, iprepad,
379 $ ipostpad, cpadval+4.1e+0 )
385 DO 60 j = 1, maxeigs, 1
386 CALL pcelset( z( 1+iprepad ), i, j, desca,
387 $ ( 13.0e+0, 1.34e+0 ) )
396 CALL pcheevx( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
397 $ vl, vu, il, iu, abstol, m, nz, wnew( 1+iprepad ),
398 $ orfac, z( 1+iprepad ), ia, ja, desca,
399 $ work( 1+iprepad ), sizeheevx, rwork( 1+iprepad ),
400 $ lwork1, iwork( 1+iprepad ), liwork,
401 $ ifail( 1+iprepad ), iclustr( 1+iprepad ),
402 $ gap( 1+iprepad ), info )
406 IF( thresh.LE.0 )
THEN
409 CALL pcchekpad( desca( ctxt_ ),
'PCHEEVX-A', np, nq, a,
410 $ desca( lld_ ), iprepad, ipostpad, cpadval )
412 CALL pcchekpad( descz( ctxt_ ),
'PCHEEVX-Z', np, mq, z,
413 $ descz( lld_ ), iprepad, ipostpad,
416 CALL pschekpad( desca( ctxt_ ),
'PCHEEVX-WNEW', n, 1, wnew, n,
417 $ iprepad, ipostpad, padval+2.0e+0 )
419 CALL pschekpad( desca( ctxt_ ),
'PCHEEVX-GAP', nprow*npcol, 1,
420 $ gap, nprow*npcol, iprepad, ipostpad,
423 CALL pschekpad( desca( ctxt_ ),
'PCHEEVX-rWORK', lwork1, 1,
424 $ rwork, lwork1, iprepad, ipostpad,
427 CALL pcchekpad( desca( ctxt_ ),
'PCHEEVX-WORK', lwork, 1, work,
428 $ lwork, iprepad, ipostpad, cpadval+4.1e+0 )
430 CALL pichekpad( desca( ctxt_ ),
'PCHEEVX-IWORK', liwork, 1,
431 $ iwork, liwork, iprepad, ipostpad, ipadval )
433 CALL pichekpad( desca( ctxt_ ),
'PCHEEVX-IFAIL', n, 1, ifail,
434 $ n, iprepad, ipostpad, ipadval )
436 CALL pichekpad( desca( ctxt_ ),
'PCHEEVX-ICLUSTR',
437 $ 2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
438 $ iprepad, ipostpad, ipadval )
443 IF( lsame( range,
'A' ) )
THEN
445 $ dseed, wnew( 1+iprepad ), maxsize,
458 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
460 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1, 1,
464 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
466 $
WRITE( nout, fmt = * )
467 $
'Different processes return different INFO'
469 ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
472 $
WRITE( nout, fmt = 9999 )info
474 ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize )
THEN
476 $
WRITE( nout, fmt = 9996 )info
478 ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize )
THEN
480 $
WRITE( nout, fmt = 9996 )info
485 IF( lsame( jobz,
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
486 $ 0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) )
THEN
488 $
WRITE( nout, fmt = 9995 )
494 IF( ( m.LT.0 ) .OR. ( m.GT.n ) )
THEN
496 $
WRITE( nout, fmt = 9994 )
498 ELSE IF( lsame( range,
'A' ) .AND. ( m.NE.n ) )
THEN
500 $
WRITE( nout, fmt = 9993 )
502 ELSE IF( lsame( range,
'I' ) .AND. ( m.NE.iu-il+1 ) )
THEN
504 $
WRITE( nout, fmt = 9992 )
506 ELSE IF( lsame( jobz,
'V' ) .AND.
507 $ ( .NOT.( lsame( range,
'V' ) ) ) .AND. ( m.NE.nz ) )
510 $
WRITE( nout, fmt = 9991 )
516 IF( lsame( jobz,
'V' ) )
THEN
517 IF( lsame( range,
'V' ) )
THEN
520 $
WRITE( nout, fmt = 9990 )
523 IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 )
THEN
525 $
WRITE( nout, fmt = 9989 )
531 $
WRITE( nout, fmt = 9988 )
536 IF( result.EQ.0 )
THEN
543 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
545 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
548 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
550 $
WRITE( nout, fmt = 9987 )
557 rwork( i ) = wnew( i+iprepad )
558 rwork( i+m ) = wnew( i+iprepad )
561 CALL sgamn2d( desca( ctxt_ ),
'a',
' ', m, 1, rwork, m,
563 CALL sgamx2d( desca( ctxt_ ),
'a',
' ', m, 1,
564 $ rwork( 1+m ), m, 1, 1, -1, -1, 0 )
568 IF( result.EQ.0 .AND. ( abs( rwork( i )-rwork( m+
569 $ i ) ).GT.five*eps*abs( rwork( i ) ) ) )
THEN
571 $
WRITE( nout, fmt = 9986 )
580 IF( lsame( jobz,
'V' ) )
THEN
582 DO 100 i = 0, nprow*npcol - 1
583 IF( iclustr( 1+iprepad+2*i ).EQ.0 )
585 nclusters = nclusters + 1
588 itmp( 1 ) = nclusters
589 itmp( 2 ) = nclusters
591 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
593 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
596 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
598 $
WRITE( nout, fmt = 9985 )
604 DO 120 i = 1, nclusters
605 iwork( indiwrk+i ) = iclustr( i+iprepad )
606 iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
608 CALL igamn2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
609 $ iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
611 CALL igamx2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
612 $ iwork( indiwrk+1+nclusters ),
613 $ nclusters*2+1, 1, 1, -1, -1, 0 )
616 DO 130 i = 1, nclusters
617 IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
618 $ iwork( indiwrk+nclusters+i ) )
THEN
620 $
WRITE( nout, fmt = 9984 )
625 IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 )
THEN
627 $
WRITE( nout, fmt = 9983 )
634 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1,
644 epsnorma = pclanhe(
'I', uplo, n, copya, ia, ja, desca,
658 IF( lsame( jobz,
'V' ) )
THEN
662 CALL psfillpad( desca( ctxt_ ), rsizechk, 1, rwork,
663 $ rsizechk, iprepad, ipostpad, 4.3e+0 )
665 CALL pcsepchk( 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 $ rsizechk, tstnrm, res )
672 CALL pschekpad( desca( ctxt_ ),
'PCSEPCHK-rWORK', rsizechk,
673 $ 1, rwork, rsizechk, iprepad, ipostpad,
681 CALL psfillpad( desca( ctxt_ ), rsizeqtq, 1, rwork,
682 $ rsizeqtq, iprepad, ipostpad, 4.3e+0 )
685 CALL pcsepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
686 $ a( 1+iprepad ), ia, ja, desca,
687 $ iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
688 $ gap( 1+iprepad ), rwork( iprepad+1 ),
689 $ rsizeqtq, qtqnrm, info, res )
691 CALL pschekpad( desca( ctxt_ ),
'PCSEPQTQ-rWORK', rsizeqtq,
692 $ 1, rwork, rsizeqtq, iprepad, ipostpad,
700 $
WRITE( nout, fmt = 9998 )info
713 IF( lsame( range,
'V' ) )
THEN
718 IF( lsame( range,
'A' ) )
THEN
730 DO 150 myil = minil, maxil
735 misssmallest = .true.
736 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.1 ) )
737 $ misssmallest = .false.
738 IF( misssmallest .AND. ( win( myil-1 ).LT.vl+normwin*
739 $ five*thresh*eps ) )misssmallest = .false.
741 IF( .NOT.lsame( range,
'V' ) .OR. ( myil.EQ.maxil ) )
742 $ misslargest = .false.
743 IF( misslargest .AND. ( win( myil+m ).GT.vu-normwin*five*
744 $ thresh*eps ) )misslargest = .false.
745 IF( .NOT.misssmallest )
THEN
746 IF( .NOT.misslargest )
THEN
751 error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
752 maxerror =
max( maxerror, error )
755 minerror =
min( maxerror, minerror )
766 IF( lsame( jobz,
'V' ) .AND. lsame( range,
'A' ) )
THEN
767 IF( minerror.GT.normwin*five*five*thresh*eps )
THEN
769 $
WRITE( nout, fmt = 9997 )minerror, normwin
773 IF( minerror.GT.normwin*five*thresh*eps )
THEN
775 $
WRITE( nout, fmt = 9997 )minerror, normwin
784 IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
787 $
WRITE( nout, fmt = 9982 )
791 IF( lsame( jobz,
'N' ) .AND. ( nz.NE.oldnz ) )
THEN
793 $
WRITE( nout, fmt = 9981 )
801 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1, -1,
809 9999
FORMAT(
'PCHEEVX returned INFO=', i7 )
810 9998
FORMAT(
'PCSEPQTQ returned INFO=', i7 )
811 9997
FORMAT(
'PCSEPSUBTST minerror =', d11.2,
' normwin=', d11.2 )
812 9996
FORMAT(
'PCHEEVX returned INFO=', i7,
813 $
' despite adequate workspace' )
814 9995
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
815 9994
FORMAT(
'M not in the range 0 to N' )
816 9993
FORMAT(
'M not equal to N' )
817 9992
FORMAT(
'M not equal to IU-IL+1' )
818 9991
FORMAT(
'M not equal to NZ' )
819 9990
FORMAT(
'NZ > M' )
820 9989
FORMAT(
'NZ < M' )
821 9988
FORMAT(
'NZ not equal to M' )
822 9987
FORMAT(
'Different processes return different values for M' )
823 9986
FORMAT(
'Different processes return different eigenvalues' )
824 9985
FORMAT(
'Different processes return ',
825 $
'different numbers of clusters' )
826 9984
FORMAT(
'Different processes return different clusters' )
827 9983
FORMAT(
'ICLUSTR not zero terminated' )
828 9982
FORMAT(
'IL, IU, VL or VU altered by PCHEEVX' )
829 9981
FORMAT(
'NZ altered by PCHEEVX with JOBZ=N' )