5
6
7
8
9
10
11
12 CHARACTER JOBZ, RANGE, UPLO
13 INTEGER IA, IL, INFO, IU, IZ, JA, JZ, LIWORK, LWORK, M,
14 $ N, NZ
15 REAL ABSTOL, ORFAC, VL, VU
16
17
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
20 REAL A( * ), GAP( * ), W( * ), WORK( * ), Z( * )
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
465 $ MB_, NB_, RSRC_, CSRC_, LLD_
466 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
467 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
468 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
469 REAL ZERO, ONE, TEN, FIVE
470 parameter( zero = 0.0e+0, one = 1.0e+0, ten = 10.0e+0,
471 $ five = 5.0e+0 )
472 INTEGER IERREIN, IERRCLS, IERRSPC, IERREBZ
473 parameter( ierrein = 1, ierrcls = 2, ierrspc = 4,
474 $ ierrebz = 8 )
475
476
477 LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, QUICKRETURN,
478 $ VALEIG, WANTZ
479 CHARACTER ORDER
480 INTEGER ANB, CSRC_A, I, IAROW, ICOFFA, ICTXT, IINFO,
481 $ INDD, INDD2, INDE, INDE2, INDIBL, INDISP,
482 $ INDTAU, INDWORK, IROFFA, IROFFZ, ISCALE,
483 $ ISIZESTEBZ, ISIZESTEIN, IZROW, LALLWORK,
484 $ LIWMIN, LLWORK, LWMIN, LWOPT, MAXEIGS, MB_A,
485 $ MQ0, MYCOL, MYROW, NB, NB_A, NEIG, NN, NNP,
486 $ NP0, NPCOL, NPROCS, NPROW, NPS, NSPLIT,
487 $ NSYTRD_LWOPT, NZZ, OFFSET, RSRC_A, RSRC_Z,
488 $ SIZEORMTR, SIZESTEIN, SIZESYEVX, SQNPC
489 REAL ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
490 $ SIGMA, SMLNUM, VLL, VUU
491
492
493 INTEGER IDUM1( 4 ), IDUM2( 4 )
494
495
496 LOGICAL LSAME
497 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
498 REAL PSLAMCH, PSLANSY
501
502
506 $ sgebs2d, slasrt, sscal
507
508
509 INTRINSIC abs, dble, ichar, int,
max,
min, mod, real,
510 $ sqrt
511
512
513
514 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
515 $ rsrc_.LT.0 )RETURN
516
517 quickreturn = ( n.EQ.0 )
518
519
520
521 ictxt = desca( ctxt_ )
522 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
523 info = 0
524
525 wantz =
lsame( jobz,
'V' )
526 IF( nprow.EQ.-1 ) THEN
527 info = -( 800+ctxt_ )
528 ELSE IF( wantz ) THEN
529 IF( ictxt.NE.descz( ctxt_ ) ) THEN
530 info = -( 2100+ctxt_ )
531 END IF
532 END IF
533 IF( info.EQ.0 ) THEN
534 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
535 IF( wantz )
536 $
CALL chk1mat( n, 4, n, 4, iz, jz, descz, 21, info )
537
538 IF( info.EQ.0 ) THEN
539
540
541
542 safmin =
pslamch( ictxt,
'Safe minimum' )
543 eps =
pslamch( ictxt,
'Precision' )
544 smlnum = safmin / eps
545 bignum = one / smlnum
546 rmin = sqrt( smlnum )
547 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
548
549 nprocs = nprow*npcol
550 lower =
lsame( uplo,
'L' )
551 alleig =
lsame( range,
'A' )
552 valeig =
lsame( range,
'V' )
553 indeig =
lsame( range,
'I' )
554
555
556
557 indtau = 1
558 inde = indtau + n
559 indd = inde + n
560 indd2 = indd + n
561 inde2 = indd2 + n
562 indwork = inde2 + n
563 llwork = lwork - indwork + 1
564
565
566
567 isizestein = 3*n + nprocs + 1
568 isizestebz =
max( 4*n, 14, nprocs )
569 indibl = (
max( isizestein, isizestebz ) ) + 1
570 indisp = indibl + n
571
572
573
574 lquery = .false.
575 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 )
576 $ lquery = .true.
577
578 nnp =
max( n, nprocs+1, 4 )
579 liwmin = 6*nnp
580
581 nprocs = nprow*npcol
582 nb_a = desca( nb_ )
583 mb_a = desca( mb_ )
584 nb = nb_a
586
587 rsrc_a = desca( rsrc_ )
588 csrc_a = desca( csrc_ )
589 iroffa = mod( ia-1, mb_a )
590 icoffa = mod( ja-1, nb_a )
591 iarow =
indxg2p( 1, nb_a, myrow, rsrc_a, nprow )
592 np0 =
numroc( n+iroffa, nb, 0, 0, nprow )
593 mq0 =
numroc( n+icoffa, nb, 0, 0, npcol )
594 IF( wantz ) THEN
595 rsrc_z = descz( rsrc_ )
596 iroffz = mod( iz-1, mb_a )
597 izrow =
indxg2p( 1, nb_a, myrow, rsrc_z, nprow )
598 ELSE
599 iroffz = 0
600 izrow = 0
601 END IF
602
603 IF( ( .NOT.wantz ) .OR. ( valeig .AND. ( .NOT.lquery ) ) )
604 $ THEN
605 lwmin = 5*n +
max( 5*nn, nb*( np0+1 ) )
606 IF( wantz ) THEN
607 mq0 =
numroc(
max( n, nb, 2 ), nb, 0, 0, npcol )
608 lwopt = 5*n +
max( 5*nn, np0*mq0+2*nb*nb )
609 ELSE
610 lwopt = lwmin
611 END IF
612 neig = 0
613 ELSE
614 IF( alleig .OR. valeig ) THEN
615 neig = n
616 ELSE IF( indeig ) THEN
617 neig = iu - il + 1
618 END IF
619 mq0 =
numroc(
max( neig, nb, 2 ), nb, 0, 0, npcol )
620 lwmin = 5*n +
max( 5*nn, np0*mq0+2*nb*nb ) +
621 $
iceil( neig, nprow*npcol )*nn
622 lwopt = lwmin
623
624 END IF
625
626
627
628
629 anb =
pjlaenv( ictxt, 3,
'PSSYTTRD',
'L', 0, 0, 0, 0 )
630 sqnpc = int( sqrt( dble( nprow*npcol ) ) )
631 nps =
max(
numroc( n, 1, 0, 0, sqnpc ), 2*anb )
632 nsytrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+4 )*nps
633 lwopt =
max( lwopt, 5*n+nsytrd_lwopt )
634
635 END IF
636 IF( info.EQ.0 ) THEN
637 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
638 work( 1 ) = abstol
639 IF( valeig ) THEN
640 work( 2 ) = vl
641 work( 3 ) = vu
642 ELSE
643 work( 2 ) = zero
644 work( 3 ) = zero
645 END IF
646 CALL sgebs2d( ictxt, 'ALL', ' ', 3, 1, work, 3 )
647 ELSE
648 CALL sgebr2d( ictxt, 'ALL', ' ', 3, 1, work, 3, 0, 0 )
649 END IF
650 IF( .NOT.( wantz .OR.
lsame( jobz,
'N' ) ) )
THEN
651 info = -1
652 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
653 info = -2
654 ELSE IF( .NOT.( lower .OR.
lsame( uplo,
'U' ) ) )
THEN
655 info = -3
656 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl ) THEN
657 info = -10
658 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
659 $ THEN
660 info = -11
661 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
662 $ THEN
663 info = -12
664 ELSE IF( lwork.LT.lwmin .AND. lwork.NE.-1 ) THEN
665 info = -23
666 ELSE IF( liwork.LT.liwmin .AND. liwork.NE.-1 ) THEN
667 info = -25
668 ELSE IF( valeig .AND. ( abs( work( 2 )-vl ).GT.five*eps*
669 $ abs( vl ) ) ) THEN
670 info = -9
671 ELSE IF( valeig .AND. ( abs( work( 3 )-vu ).GT.five*eps*
672 $ abs( vu ) ) ) THEN
673 info = -10
674 ELSE IF( abs( work( 1 )-abstol ).GT.five*eps*abs( abstol ) )
675 $ THEN
676 info = -13
677 ELSE IF( iroffa.NE.0 ) THEN
678 info = -6
679 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
680 info = -( 800+nb_ )
681 END IF
682 IF( wantz ) THEN
683 IF( iroffa.NE.iroffz ) THEN
684 info = -19
685 ELSE IF( iarow.NE.izrow ) THEN
686 info = -19
687 ELSE IF( desca( m_ ).NE.descz( m_ ) ) THEN
688 info = -( 2100+m_ )
689 ELSE IF( desca( n_ ).NE.descz( n_ ) ) THEN
690 info = -( 2100+n_ )
691 ELSE IF( desca( mb_ ).NE.descz( mb_ ) ) THEN
692 info = -( 2100+mb_ )
693 ELSE IF( desca( nb_ ).NE.descz( nb_ ) ) THEN
694 info = -( 2100+nb_ )
695 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) ) THEN
696 info = -( 2100+rsrc_ )
697 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) ) THEN
698 info = -( 2100+csrc_ )
699 ELSE IF( ictxt.NE.descz( ctxt_ ) ) THEN
700 info = -( 2100+ctxt_ )
701 END IF
702 END IF
703 END IF
704 IF( wantz ) THEN
705 idum1( 1 ) = ichar( 'V' )
706 ELSE
707 idum1( 1 ) = ichar( 'N' )
708 END IF
709 idum2( 1 ) = 1
710 IF( lower ) THEN
711 idum1( 2 ) = ichar( 'L' )
712 ELSE
713 idum1( 2 ) = ichar( 'U' )
714 END IF
715 idum2( 2 ) = 2
716 IF( alleig ) THEN
717 idum1( 3 ) = ichar( 'A' )
718 ELSE IF( indeig ) THEN
719 idum1( 3 ) = ichar( 'I' )
720 ELSE
721 idum1( 3 ) = ichar( 'V' )
722 END IF
723 idum2( 3 ) = 3
724 IF( lquery ) THEN
725 idum1( 4 ) = -1
726 ELSE
727 idum1( 4 ) = 1
728 END IF
729 idum2( 4 ) = 4
730 IF( wantz ) THEN
731 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 8, n, 4, n, 4, iz,
732 $ jz, descz, 21, 4, idum1, idum2, info )
733 ELSE
734 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 4, idum1,
735 $ idum2, info )
736 END IF
737 work( 1 ) = real( lwopt )
738 iwork( 1 ) = liwmin
739 END IF
740
741 IF( info.NE.0 ) THEN
742 CALL pxerbla( ictxt,
'PSSYEVX', -info )
743 RETURN
744 ELSE IF( lquery ) THEN
745 RETURN
746 END IF
747
748
749
750 IF( quickreturn ) THEN
751 IF( wantz ) THEN
752 nz = 0
753 iclustr( 1 ) = 0
754 END IF
755 m = 0
756 work( 1 ) = real( lwopt )
757 iwork( 1 ) = liwmin
758 RETURN
759 END IF
760
761
762
763 abstll = abstol
764 iscale = 0
765 IF( valeig ) THEN
766 vll = vl
767 vuu = vu
768 ELSE
769 vll = zero
770 vuu = zero
771 END IF
772
773 anrm =
pslansy(
'M', uplo, n, a, ia, ja, desca, work( indwork ) )
774
775 IF( anrm.GT.zero .AND. anrm.LT.rmin ) THEN
776 iscale = 1
777 sigma = rmin / anrm
778 anrm = anrm*sigma
779 ELSE IF( anrm.GT.rmax ) THEN
780 iscale = 1
781 sigma = rmax / anrm
782 anrm = anrm*sigma
783 END IF
784
785 IF( iscale.EQ.1 ) THEN
786 CALL pslascl( uplo, one, sigma, n, n, a, ia, ja, desca, iinfo )
787 IF( abstol.GT.0 )
788 $ abstll = abstol*sigma
789 IF( valeig ) THEN
790 vll = vl*sigma
791 vuu = vu*sigma
792 IF( vuu.EQ.vll ) THEN
793 vuu = vuu + 2*
max( abs( vuu )*eps, safmin )
794 END IF
795 END IF
796 END IF
797
798
799
800 lallwork = llwork
801
802 CALL pssyntrd( uplo, n, a, ia, ja, desca, work( indd ),
803 $ work( inde ), work( indtau ), work( indwork ),
804 $ llwork, iinfo )
805
806
807
808
809
810
811
812
813 offset = 0
814 IF( ia.EQ.1 .AND. ja.EQ.1 .AND. rsrc_a.EQ.0 .AND. csrc_a.EQ.0 )
815 $ THEN
816 CALL pslared1d( n, ia, ja, desca, work( indd ), work( indd2 ),
817 $ work( indwork ), llwork )
818
819 CALL pslared1d( n, ia, ja, desca, work( inde ), work( inde2 ),
820 $ work( indwork ), llwork )
821 IF( .NOT.lower )
822 $ offset = 1
823 ELSE
824 DO 10 i = 1, n
825 CALL pselget(
'A',
' ', work( indd2+i-1 ), a, i+ia-1,
826 $ i+ja-1, desca )
827 10 CONTINUE
828 IF(
lsame( uplo,
'U' ) )
THEN
829 DO 20 i = 1, n - 1
830 CALL pselget(
'A',
' ', work( inde2+i-1 ), a, i+ia-1,
831 $ i+ja, desca )
832 20 CONTINUE
833 ELSE
834 DO 30 i = 1, n - 1
835 CALL pselget(
'A',
' ', work( inde2+i-1 ), a, i+ia,
836 $ i+ja-1, desca )
837 30 CONTINUE
838 END IF
839 END IF
840
841
842
843 IF( wantz ) THEN
844 order = 'B'
845 ELSE
846 order = 'E'
847 END IF
848
849 CALL psstebz( ictxt, range, order, n, vll, vuu, il, iu, abstll,
850 $ work( indd2 ), work( inde2+offset ), m, nsplit, w,
851 $ iwork( indibl ), iwork( indisp ), work( indwork ),
852 $ llwork, iwork( 1 ), isizestebz, iinfo )
853
854
855
856
857
858
859
860
861
862 IF( iinfo.NE.0 ) THEN
863 info = info + ierrebz
864 DO 40 i = 1, m
865 iwork( indibl+i-1 ) = abs( iwork( indibl+i-1 ) )
866 40 CONTINUE
867 END IF
868 IF( wantz ) THEN
869
870 IF( valeig ) THEN
871
872
873
874
875
876
877
878
879
880
881
882 CALL igamn2d( ictxt, 'A', ' ', 1, 1, lallwork, 1, 1, 1, -1,
883 $ -1, -1 )
884
885 maxeigs = descz( n_ )
886
887 DO 50 nz =
min( maxeigs, m ), 0, -1
888 mq0 =
numroc( nz, nb, 0, 0, npcol )
889 sizestein =
iceil( nz, nprocs )*n +
max( 5*n, np0*mq0 )
890 sizeormtr =
max( ( nb*( nb-1 ) ) / 2, ( mq0+np0 )*nb ) +
891 $ nb*nb
892
893 sizesyevx =
max( sizestein, sizeormtr )
894 IF( sizesyevx.LE.lallwork )
895 $ GO TO 60
896 50 CONTINUE
897 60 CONTINUE
898 ELSE
899 nz = m
900 END IF
902 IF( nz.NE.m ) THEN
903 info = info + ierrspc
904
905 DO 70 i = 1, m
906 ifail( i ) = 0
907 70 CONTINUE
908
909
910
911
912
913
914
915
916
917
918 IF( nsplit.GT.1 ) THEN
919 CALL slasrt( 'I', m, w, iinfo )
920 nzz = 0
921 IF( nz.GT.0 ) THEN
922
923 vuu = w( nz ) - ten*( eps*anrm+safmin )
924 IF( vll.GE.vuu ) THEN
925 nzz = 0
926 ELSE
927 CALL psstebz( ictxt, range, order, n, vll, vuu, il,
928 $ iu, abstll, work( indd2 ),
929 $ work( inde2+offset ), nzz, nsplit, w,
930 $ iwork( indibl ), iwork( indisp ),
931 $ work( indwork ), llwork, iwork( 1 ),
932 $ isizestebz, iinfo )
933 END IF
934
935 IF( mod( info / ierrebz, 1 ).EQ.0 ) THEN
936 IF( nzz.GT.nz .OR. iinfo.NE.0 ) THEN
937 info = info + ierrebz
938 END IF
939 END IF
940 END IF
942
943 END IF
944 END IF
945 CALL psstein( n, work( indd2 ), work( inde2+offset ), nz, w,
946 $ iwork( indibl ), iwork( indisp ), orfac, z, iz,
947 $ jz, descz, work( indwork ), lallwork, iwork( 1 ),
948 $ isizestein, ifail, iclustr, gap, iinfo )
949
950 IF( iinfo.GE.nz+1 )
951 $ info = info + ierrcls
952 IF( mod( iinfo, nz+1 ).NE.0 )
953 $ info = info + ierrein
954
955
956
957
958 IF( nz.GT.0 ) THEN
959 CALL psormtr(
'L', uplo,
'N', n, nz, a, ia, ja, desca,
960 $ work( indtau ), z, iz, jz, descz,
961 $ work( indwork ), llwork, iinfo )
962 END IF
963
964 END IF
965
966
967
968 IF( iscale.EQ.1 ) THEN
969 CALL sscal( m, one / sigma, w, 1 )
970 END IF
971
972 work( 1 ) = real( lwopt )
973 iwork( 1 ) = liwmin
974
975 RETURN
976
977
978
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
integer function iceil(inum, idenom)
integer function indxg2p(indxglob, nb, iproc, isrcproc, nprocs)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
real function pslamch(ictxt, cmach)
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
subroutine pchk2mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, mb, mbpos0, nb, nbpos0, ib, jb, descb, descbpos0, nextra, ex, expos, info)
integer function pjlaenv(ictxt, ispec, name, opts, n1, n2, n3, n4)
subroutine pselget(scope, top, alpha, a, ia, ja, desca)
real function pslansy(norm, uplo, n, a, ia, ja, desca, work)
subroutine pslared1d(n, ia, ja, desc, bycol, byall, work, lwork)
subroutine pslascl(type, cfrom, cto, m, n, a, ia, ja, desca, info)
subroutine psormtr(side, uplo, trans, m, n, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine psstebz(ictxt, range, order, n, vl, vu, il, iu, abstol, d, e, m, nsplit, w, iblock, isplit, work, lwork, iwork, liwork, info)
subroutine psstein(n, d, e, m, w, iblock, isplit, orfac, z, iz, jz, descz, work, lwork, iwork, liwork, ifail, iclustr, gap, info)
subroutine pssyntrd(uplo, n, a, ia, ja, desca, d, e, tau, work, lwork, info)
subroutine pxerbla(ictxt, srname, info)