1 SUBROUTINE pssepsubtst( 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 REAL ABSTOL, QTQNRM, THRESH, TSTNRM, VL, VU
21 INTEGER DESCA( * ), ICLUSTR( * ), IFAIL( * ),
23 REAL 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 REAL PADVAL, FIVE, NEGONE
202 PARAMETER ( PADVAL = 13.5285e+0, five = 5.0e+0,
205 PARAMETER ( IPADVAL = 927 )
208 INTEGER I, IAM, INDIWRK, INFO, ISIZESUBTST, ISIZESYEVX,
209 $ isizetst, j, m, maxeigs, maxil, maxiu, maxsize,
210 $ minil, mq, mycol, myil, myrow, nclusters, np,
211 $ npcol, nprow, nq, nz, oldil, oldiu, oldnz, res,
212 $ sizechk, sizemqrleft, sizemqrright, sizeqrf,
213 $ sizeqtq, sizesubtst, sizesyevx, sizetms,
214 $ sizetst, valsize, vecsize
215 REAL EPS, EPSNORMA, ERROR, MAXERROR, MAXVU,
216 $ MINERROR, MINVL, NORMWIN, OLDVL, OLDVU, ORFAC,
220 INTEGER DESCZ( DLEN_ ), DSEED( 4 ), ITMP( 2 )
226 REAL PSLAMCH, PSLANSY
227 EXTERNAL LSAME, NUMROC, PSLAMCH, PSLANSY
230 EXTERNAL blacs_gridinfo,
descinit, igamn2d, igamx2d,
237 INTRINSIC abs,
max,
min, mod
241 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
243 CALL pslasizesep( desca, iprepad, ipostpad, sizemqrleft,
244 $ sizemqrright, sizeqrf, sizetms, sizeqtq,
245 $ sizechk, sizesyevx, isizesyevx, sizesubtst,
246 $ isizesubtst, sizetst, isizetst )
250 eps = pslamch( desca( ctxt_ ),
'Eps' )
251 safmin = pslamch( desca( ctxt_ ),
'Safe min' )
252 normwin = safmin / eps
254 $ normwin =
max( abs( win( 1 ) ), abs( win( n ) ), normwin )
266 DO 10 i = 1, lwork1, 1
267 work( i+iprepad ) = 14.3e+0
269 DO 20 i = 1, liwork, 1
270 iwork( i+iprepad ) = 14
274 wnew( i+iprepad ) = 3.14159e+0
277 iclustr( 1+iprepad ) = 139
279 IF( lsame( jobz,
'N' ) )
THEN
282 IF( lsame( range,
'A' ) )
THEN
284 ELSE IF( lsame( range,
'I' ) )
THEN
285 maxeigs = iu - il + 1
287 minvl = vl - normwin*five*eps - abstol
288 maxvu = vu + normwin*five*eps + abstol
292 IF( win( i ).LT.minvl )
294 IF( win( i ).LE.maxvu )
298 maxeigs = maxiu - minil + 1
303 CALL descinit( descz, desca( m_ ), desca( n_ ), desca( mb_ ),
304 $ desca( nb_ ), desca( rsrc_ ), desca( csrc_ ),
305 $ desca( ctxt_ ), desca( lld_ ), info )
307 CALL blacs_gridinfo( desca( ctxt_ ), nprow, npcol, myrow, mycol )
308 indiwrk = 1 + iprepad + nprow*npcol + 1
311 IF( myrow.EQ.0 .AND. mycol.EQ.0 )
317 IF( myrow.GE.nprow .OR. myrow.LT.0 )
328 $ dseed, win, maxsize, vecsize, valsize )
330 np = numroc( n, desca( mb_ ), myrow, 0, nprow )
331 nq = numroc( n, desca( nb_ ), mycol, 0, npcol )
332 mq = numroc( maxeigs, desca( nb_ ), mycol, 0, npcol )
334 CALL slacpy(
'A', np, nq, copya, desca( lld_ ), a( 1+iprepad ),
337 CALL psfillpad( desca( ctxt_ ), np, nq, a, desca( lld_ ), iprepad,
340 CALL psfillpad( descz( ctxt_ ), np, mq, z, descz( lld_ ), iprepad,
341 $ ipostpad, padval+1.0e+0 )
343 CALL psfillpad( desca( ctxt_ ), n, 1, wnew, n, iprepad, ipostpad,
346 CALL psfillpad( desca( ctxt_ ), nprow*npcol, 1, gap, nprow*npcol,
347 $ iprepad, ipostpad, padval+3.0e+0 )
349 CALL psfillpad( desca( ctxt_ ), lwork1, 1, work, lwork1, iprepad,
350 $ ipostpad, padval+4.0e+0 )
352 CALL pifillpad( desca( ctxt_ ), liwork, 1, iwork, liwork, iprepad,
353 $ ipostpad, ipadval )
355 CALL pifillpad( desca( ctxt_ ), n, 1, ifail, n, iprepad, ipostpad,
358 CALL pifillpad( desca( ctxt_ ), 2*nprow*npcol, 1, iclustr,
359 $ 2*nprow*npcol, iprepad, ipostpad, ipadval )
365 DO 50 j = 1, maxeigs, 1
366 CALL pselset( z( 1+iprepad ), i, j, desca, 13.0e+0 )
375 CALL pssyevx( jobz, range, uplo, n, a( 1+iprepad ), ia, ja, desca,
376 $ vl, vu, il, iu, abstol, m, nz, wnew( 1+iprepad ),
377 $ orfac, z( 1+iprepad ), ia, ja, desca,
378 $ work( 1+iprepad ), lwork1, iwork( 1+iprepad ),
379 $ liwork, ifail( 1+iprepad ), iclustr( 1+iprepad ),
380 $ gap( 1+iprepad ), info )
384 IF( thresh.LE.0 )
THEN
387 CALL pschekpad( desca( ctxt_ ),
'PSSYEVX-A', np, nq, a,
388 $ desca( lld_ ), iprepad, ipostpad, padval )
390 CALL pschekpad( descz( ctxt_ ),
'PSSYEVX-Z', np, mq, z,
391 $ descz( lld_ ), iprepad, ipostpad,
394 CALL pschekpad( desca( ctxt_ ),
'PSSYEVX-WNEW', n, 1, wnew, n,
395 $ iprepad, ipostpad, padval+2.0e+0 )
397 CALL pschekpad( desca( ctxt_ ),
'PSSYEVX-GAP', nprow*npcol, 1,
398 $ gap, nprow*npcol, iprepad, ipostpad,
401 CALL pschekpad( desca( ctxt_ ),
'PSSYEVX-WORK', lwork1, 1,
402 $ work, lwork1, iprepad, ipostpad,
405 CALL pichekpad( desca( ctxt_ ),
'PSSYEVX-IWORK', liwork, 1,
406 $ iwork, liwork, iprepad, ipostpad, ipadval )
408 CALL pichekpad( desca( ctxt_ ),
'PSSYEVX-IFAIL', n, 1, ifail,
409 $ n, iprepad, ipostpad, ipadval )
411 CALL pichekpad( desca( ctxt_ ),
'PSSYEVX-ICLUSTR',
412 $ 2*nprow*npcol, 1, iclustr, 2*nprow*npcol,
413 $ iprepad, ipostpad, ipadval )
418 IF( lsame( range,
'A' ) )
THEN
420 $ dseed, wnew( 1+iprepad ), maxsize,
433 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
435 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1, 1,
439 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
441 $
WRITE( nout, fmt = * )
442 $
'Different processes return different INFO'
444 ELSE IF( mod( info, 2 ).EQ.1 .OR. info.GT.7 .OR. info.LT.0 )
447 $
WRITE( nout, fmt = 9999 )info
449 ELSE IF( mod( info / 2, 2 ).EQ.1 .AND. lwork1.GE.maxsize )
THEN
451 $
WRITE( nout, fmt = 9996 )info
453 ELSE IF( mod( info / 4, 2 ).EQ.1 .AND. lwork1.GE.vecsize )
THEN
455 $
WRITE( nout, fmt = 9996 )info
460 IF( lsame( jobz,
'V' ) .AND. ( iclustr( 1+iprepad ).NE.
461 $ 0 ) .AND. ( mod( info / 2, 2 ).NE.1 ) )
THEN
463 $
WRITE( nout, fmt = 9995 )
469 IF( ( m.LT.0 ) .OR. ( m.GT.n ) )
THEN
471 $
WRITE( nout, fmt = 9994 )
473 ELSE IF( lsame( range,
'A' ) .AND. ( m.NE.n ) )
THEN
475 $
WRITE( nout, fmt = 9993 )
477 ELSE IF( lsame( range,
'I' ) .AND. ( m.NE.iu-il+1 ) )
THEN
479 $
WRITE( nout, fmt = 9992 )
481 ELSE IF( lsame( jobz,
'V' ) .AND.
482 $ ( .NOT.( lsame( range,
'V' ) ) ) .AND. ( m.NE.nz ) )
485 $
WRITE( nout, fmt = 9991 )
491 IF( lsame( jobz,
'V' ) )
THEN
492 IF( lsame( range,
'V' ) )
THEN
495 $
WRITE( nout, fmt = 9990 )
498 IF( nz.LT.m .AND. mod( info / 4, 2 ).NE.1 )
THEN
500 $
WRITE( nout, fmt = 9989 )
506 $
WRITE( nout, fmt = 9988 )
511 IF( result.EQ.0 )
THEN
518 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
520 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
523 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
525 $
WRITE( nout, fmt = 9987 )
532 work( i ) = wnew( i+iprepad )
533 work( i+m ) = wnew( i+iprepad )
536 CALL sgamn2d( desca( ctxt_ ),
'a',
' ', m, 1, work, m, 1,
538 CALL sgamx2d( desca( ctxt_ ),
'a',
' ', m, 1,
539 $ work( 1+m ), m, 1, 1, -1, -1, 0 )
542 IF( result.EQ.0 .AND. work( i ).NE.work( m+i ) )
THEN
544 $
WRITE( nout, fmt = 9986 )
553 IF( lsame( jobz,
'V' ) )
THEN
555 DO 90 i = 0, nprow*npcol - 1
556 IF( iclustr( 1+iprepad+2*i ).EQ.0 )
558 nclusters = nclusters + 1
561 itmp( 1 ) = nclusters
562 itmp( 2 ) = nclusters
564 CALL igamn2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp, 1, 1, 1,
566 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, itmp( 2 ), 1,
569 IF( itmp( 1 ).NE.itmp( 2 ) )
THEN
571 $
WRITE( nout, fmt = 9985 )
577 DO 110 i = 1, nclusters
578 iwork( indiwrk+i ) = iclustr( i+iprepad )
579 iwork( indiwrk+i+nclusters ) = iclustr( i+iprepad )
581 CALL igamn2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
582 $ iwork( indiwrk+1 ), nclusters*2+1, 1, 1,
584 CALL igamx2d( desca( ctxt_ ),
'a',
' ', nclusters*2+1, 1,
585 $ iwork( indiwrk+1+nclusters ),
586 $ nclusters*2+1, 1, 1, -1, -1, 0 )
589 DO 120 i = 1, nclusters
590 IF( result.EQ.0 .AND. iwork( indiwrk+i ).NE.
591 $ iwork( indiwrk+nclusters+i ) )
THEN
593 $
WRITE( nout, fmt = 9984 )
598 IF( iclustr( 1+iprepad+nclusters*2 ).NE.0 )
THEN
600 $
WRITE( nout, fmt = 9983 )
607 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1,
617 epsnorma = pslansy(
'I', uplo, n, copya, ia, ja, desca,
631 IF( lsame( jobz,
'V' ) )
THEN
635 CALL psfillpad( desca( ctxt_ ), sizechk, 1, work, sizechk,
636 $ iprepad, ipostpad, 4.3e+0 )
638 CALL pssepchk( n, nz, copya, ia, ja, desca,
639 $
max( abstol+epsnorma, safmin ), thresh,
640 $ z( 1+iprepad ), ia, ja, descz,
641 $ a( 1+iprepad ), ia, ja, desca,
642 $ wnew( 1+iprepad ), work( 1+iprepad ),
643 $ sizechk, tstnrm, res )
645 CALL pschekpad( desca( ctxt_ ),
'PSSEPCHK-WORK', sizechk, 1,
646 $ work, sizechk, iprepad, ipostpad, 4.3e+0 )
653 CALL psfillpad( desca( ctxt_ ), sizeqtq, 1, work, sizeqtq,
654 $ iprepad, ipostpad, 4.3e+0 )
657 CALL pssepqtq( n, nz, thresh, z( 1+iprepad ), ia, ja, descz,
658 $ a( 1+iprepad ), ia, ja, desca,
659 $ iwork( 1+iprepad+1 ), iclustr( 1+iprepad ),
660 $ gap( 1+iprepad ), work( iprepad+1 ), sizeqtq,
661 $ qtqnrm, info, res )
663 CALL pschekpad( desca( ctxt_ ),
'PSSEPQTQ-WORK', sizeqtq, 1,
664 $ work, sizeqtq, iprepad, ipostpad, 4.3e+0 )
671 $
WRITE( nout, fmt = 9998 )info
684 IF( lsame( range,
'V' ) )
THEN
689 IF( lsame( range,
'A' ) )
THEN
701 DO 140 myil = minil, maxil
706 IF( .NOT.lsame( range,
'V' ) .OR.
707 $ ( myil.EQ.1 .OR. ( win( myil-1 ).LT.vl+normwin*five*
708 $ thresh*eps ) ) )
THEN
709 IF( .NOT.lsame( range,
'V' ) .OR.
710 $ ( myil.EQ.n-m+1 .OR. ( win( myil+m ).GT.vu-
711 $ normwin*five*thresh*eps ) ) )
THEN
716 error = abs( win( i+myil-1 )-wnew( i+iprepad ) )
717 maxerror =
max( maxerror, error )
720 minerror =
min( maxerror, minerror )
731 IF( lsame( jobz,
'V' ) .AND. lsame( range,
'A' ) )
THEN
732 IF( minerror.GT.normwin*five*five*thresh*eps )
THEN
734 $
WRITE( nout, fmt = 9997 )minerror, normwin
738 IF( minerror.GT.normwin*five*thresh*eps )
THEN
740 $
WRITE( nout, fmt = 9997 )minerror, normwin
749 IF( il.NE.oldil .OR. iu.NE.oldiu .OR. vl.NE.oldvl .OR. vu.NE.
752 $
WRITE( nout, fmt = 9982 )
756 IF( lsame( jobz,
'N' ) .AND. ( nz.NE.oldnz ) )
THEN
758 $
WRITE( nout, fmt = 9981 )
766 CALL igamx2d( desca( ctxt_ ),
'a',
' ', 1, 1, result, 1, 1, 1, -1,
774 9999
FORMAT(
'PSSYEVX returned INFO=', i7 )
775 9998
FORMAT(
'PSSEPQTQ returned INFO=', i7 )
776 9997
FORMAT(
'PSSEPSUBTST minerror =', d11.2,
' normwin=', d11.2 )
777 9996
FORMAT(
'PSSYEVX returned INFO=', i7,
778 $
' despite adequate workspace' )
779 9995
FORMAT( .NE..NE.
'ICLUSTR(1)0 but mod(INFO/2,2)1' )
780 9994
FORMAT(
'M not in the range 0 to N' )
781 9993
FORMAT(
'M not equal to N' )
782 9992
FORMAT(
'M not equal to IU-IL+1' )
783 9991
FORMAT(
'M not equal to NZ' )
784 9990
FORMAT(
'NZ > M' )
785 9989
FORMAT(
'NZ < M' )
786 9988
FORMAT(
'NZ not equal to M' )
787 9987
FORMAT(
'Different processes return different values for M' )
788 9986
FORMAT(
'Different processes return different eigenvalues' )
789 9985
FORMAT(
'Different processes return ',
790 $
'different numbers of clusters' )
791 9984
FORMAT(
'Different processes return different clusters' )
792 9983
FORMAT(
'ICLUSTR not zero terminated' )
793 9982
FORMAT(
'IL, IU, VL or VU altered by PSSYEVX' )
794 9981
FORMAT(
'NZ altered by PSSYEVX with JOBZ=N' )