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 DOUBLE PRECISION ABSTOL, ORFAC, VL, VU
16
17
18 INTEGER DESCA( * ), DESCZ( * ), ICLUSTR( * ),
19 $ IFAIL( * ), IWORK( * )
20 DOUBLE PRECISION 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 DOUBLE PRECISION ZERO, ONE, TEN, FIVE
470 parameter( zero = 0.0d+0, one = 1.0d+0, ten = 10.0d+0,
471 $ five = 5.0d+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 DOUBLE PRECISION 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 DOUBLE PRECISION PDLAMCH, PDLANSY
501
502
503 EXTERNAL blacs_gridinfo,
chk1mat, dgebr2d, dgebs2d,
507
508
509 INTRINSIC abs, dble, ichar, int,
max,
min, mod, sqrt
510
511
512
513 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
514 $ rsrc_.LT.0 )RETURN
515
516 quickreturn = ( n.EQ.0 )
517
518
519
520 ictxt = desca( ctxt_ )
521 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
522 info = 0
523
524 wantz =
lsame( jobz,
'V' )
525 IF( nprow.EQ.-1 ) THEN
526 info = -( 800+ctxt_ )
527 ELSE IF( wantz ) THEN
528 IF( ictxt.NE.descz( ctxt_ ) ) THEN
529 info = -( 2100+ctxt_ )
530 END IF
531 END IF
532 IF( info.EQ.0 ) THEN
533 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 8, info )
534 IF( wantz )
535 $
CALL chk1mat( n, 4, n, 4, iz, jz, descz, 21, info )
536
537 IF( info.EQ.0 ) THEN
538
539
540
541 safmin =
pdlamch( ictxt,
'Safe minimum' )
542 eps =
pdlamch( ictxt,
'Precision' )
543 smlnum = safmin / eps
544 bignum = one / smlnum
545 rmin = sqrt( smlnum )
546 rmax =
min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
547
548 nprocs = nprow*npcol
549 lower =
lsame( uplo,
'L' )
550 alleig =
lsame( range,
'A' )
551 valeig =
lsame( range,
'V' )
552 indeig =
lsame( range,
'I' )
553
554
555
556 indtau = 1
557 inde = indtau + n
558 indd = inde + n
559 indd2 = indd + n
560 inde2 = indd2 + n
561 indwork = inde2 + n
562 llwork = lwork - indwork + 1
563
564
565
566 isizestein = 3*n + nprocs + 1
567 isizestebz =
max( 4*n, 14, nprocs )
568 indibl = (
max( isizestein, isizestebz ) ) + 1
569 indisp = indibl + n
570
571
572
573 lquery = .false.
574 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 )
575 $ lquery = .true.
576
577 nnp =
max( n, nprocs+1, 4 )
578 liwmin = 6*nnp
579
580 nprocs = nprow*npcol
581 nb_a = desca( nb_ )
582 mb_a = desca( mb_ )
583 nb = nb_a
585
586 rsrc_a = desca( rsrc_ )
587 csrc_a = desca( csrc_ )
588 iroffa = mod( ia-1, mb_a )
589 icoffa = mod( ja-1, nb_a )
590 iarow =
indxg2p( 1, nb_a, myrow, rsrc_a, nprow )
591 np0 =
numroc( n+iroffa, nb, 0, 0, nprow )
592 mq0 =
numroc( n+icoffa, nb, 0, 0, npcol )
593 IF( wantz ) THEN
594 rsrc_z = descz( rsrc_ )
595 iroffz = mod( iz-1, mb_a )
596 izrow =
indxg2p( 1, nb_a, myrow, rsrc_z, nprow )
597 ELSE
598 iroffz = 0
599 izrow = 0
600 END IF
601
602 IF( ( .NOT.wantz ) .OR. ( valeig .AND. ( .NOT.lquery ) ) )
603 $ THEN
604 lwmin = 5*n +
max( 5*nn, nb*( np0+1 ) )
605 IF( wantz ) THEN
606 mq0 =
numroc(
max( n, nb, 2 ), nb, 0, 0, npcol )
607 lwopt = 5*n +
max( 5*nn, np0*mq0+2*nb*nb )
608 ELSE
609 lwopt = lwmin
610 END IF
611 neig = 0
612 ELSE
613 IF( alleig .OR. valeig ) THEN
614 neig = n
615 ELSE IF( indeig ) THEN
616 neig = iu - il + 1
617 END IF
618 mq0 =
numroc(
max( neig, nb, 2 ), nb, 0, 0, npcol )
619 lwmin = 5*n +
max( 5*nn, np0*mq0+2*nb*nb ) +
620 $
iceil( neig, nprow*npcol )*nn
621 lwopt = lwmin
622
623 END IF
624
625
626
627
628 anb =
pjlaenv( ictxt, 3,
'PDSYTTRD',
'L', 0, 0, 0, 0 )
629 sqnpc = int( sqrt( dble( nprow*npcol ) ) )
630 nps =
max(
numroc( n, 1, 0, 0, sqnpc ), 2*anb )
631 nsytrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+4 )*nps
632 lwopt =
max( lwopt, 5*n+nsytrd_lwopt )
633
634 END IF
635 IF( info.EQ.0 ) THEN
636 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
637 work( 1 ) = abstol
638 IF( valeig ) THEN
639 work( 2 ) = vl
640 work( 3 ) = vu
641 ELSE
642 work( 2 ) = zero
643 work( 3 ) = zero
644 END IF
645 CALL dgebs2d( ictxt, 'ALL', ' ', 3, 1, work, 3 )
646 ELSE
647 CALL dgebr2d( ictxt, 'ALL', ' ', 3, 1, work, 3, 0, 0 )
648 END IF
649 IF( .NOT.( wantz .OR.
lsame( jobz,
'N' ) ) )
THEN
650 info = -1
651 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
652 info = -2
653 ELSE IF( .NOT.( lower .OR.
lsame( uplo,
'U' ) ) )
THEN
654 info = -3
655 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl ) THEN
656 info = -10
657 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
658 $ THEN
659 info = -11
660 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
661 $ THEN
662 info = -12
663 ELSE IF( lwork.LT.lwmin .AND. lwork.NE.-1 ) THEN
664 info = -23
665 ELSE IF( liwork.LT.liwmin .AND. liwork.NE.-1 ) THEN
666 info = -25
667 ELSE IF( valeig .AND. ( abs( work( 2 )-vl ).GT.five*eps*
668 $ abs( vl ) ) ) THEN
669 info = -9
670 ELSE IF( valeig .AND. ( abs( work( 3 )-vu ).GT.five*eps*
671 $ abs( vu ) ) ) THEN
672 info = -10
673 ELSE IF( abs( work( 1 )-abstol ).GT.five*eps*abs( abstol ) )
674 $ THEN
675 info = -13
676 ELSE IF( iroffa.NE.0 ) THEN
677 info = -6
678 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
679 info = -( 800+nb_ )
680 END IF
681 IF( wantz ) THEN
682 IF( iroffa.NE.iroffz ) THEN
683 info = -19
684 ELSE IF( iarow.NE.izrow ) THEN
685 info = -19
686 ELSE IF( desca( m_ ).NE.descz( m_ ) ) THEN
687 info = -( 2100+m_ )
688 ELSE IF( desca( n_ ).NE.descz( n_ ) ) THEN
689 info = -( 2100+n_ )
690 ELSE IF( desca( mb_ ).NE.descz( mb_ ) ) THEN
691 info = -( 2100+mb_ )
692 ELSE IF( desca( nb_ ).NE.descz( nb_ ) ) THEN
693 info = -( 2100+nb_ )
694 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) ) THEN
695 info = -( 2100+rsrc_ )
696 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) ) THEN
697 info = -( 2100+csrc_ )
698 ELSE IF( ictxt.NE.descz( ctxt_ ) ) THEN
699 info = -( 2100+ctxt_ )
700 END IF
701 END IF
702 END IF
703 IF( wantz ) THEN
704 idum1( 1 ) = ichar( 'V' )
705 ELSE
706 idum1( 1 ) = ichar( 'N' )
707 END IF
708 idum2( 1 ) = 1
709 IF( lower ) THEN
710 idum1( 2 ) = ichar( 'L' )
711 ELSE
712 idum1( 2 ) = ichar( 'U' )
713 END IF
714 idum2( 2 ) = 2
715 IF( alleig ) THEN
716 idum1( 3 ) = ichar( 'A' )
717 ELSE IF( indeig ) THEN
718 idum1( 3 ) = ichar( 'I' )
719 ELSE
720 idum1( 3 ) = ichar( 'V' )
721 END IF
722 idum2( 3 ) = 3
723 IF( lquery ) THEN
724 idum1( 4 ) = -1
725 ELSE
726 idum1( 4 ) = 1
727 END IF
728 idum2( 4 ) = 4
729 IF( wantz ) THEN
730 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 8, n, 4, n, 4, iz,
731 $ jz, descz, 21, 4, idum1, idum2, info )
732 ELSE
733 CALL pchk1mat( n, 4, n, 4, ia, ja, desca, 8, 4, idum1,
734 $ idum2, info )
735 END IF
736 work( 1 ) = dble( lwopt )
737 iwork( 1 ) = liwmin
738 END IF
739
740 IF( info.NE.0 ) THEN
741 CALL pxerbla( ictxt,
'PDSYEVX', -info )
742 RETURN
743 ELSE IF( lquery ) THEN
744 RETURN
745 END IF
746
747
748
749 IF( quickreturn ) THEN
750 IF( wantz ) THEN
751 nz = 0
752 iclustr( 1 ) = 0
753 END IF
754 m = 0
755 work( 1 ) = dble( lwopt )
756 iwork( 1 ) = liwmin
757 RETURN
758 END IF
759
760
761
762 abstll = abstol
763 iscale = 0
764 IF( valeig ) THEN
765 vll = vl
766 vuu = vu
767 ELSE
768 vll = zero
769 vuu = zero
770 END IF
771
772 anrm =
pdlansy(
'M', uplo, n, a, ia, ja, desca, work( indwork ) )
773
774 IF( anrm.GT.zero .AND. anrm.LT.rmin ) THEN
775 iscale = 1
776 sigma = rmin / anrm
777 anrm = anrm*sigma
778 ELSE IF( anrm.GT.rmax ) THEN
779 iscale = 1
780 sigma = rmax / anrm
781 anrm = anrm*sigma
782 END IF
783
784 IF( iscale.EQ.1 ) THEN
785 CALL pdlascl( uplo, one, sigma, n, n, a, ia, ja, desca, iinfo )
786 IF( abstol.GT.0 )
787 $ abstll = abstol*sigma
788 IF( valeig ) THEN
789 vll = vl*sigma
790 vuu = vu*sigma
791 IF( vuu.EQ.vll ) THEN
792 vuu = vuu + 2*
max( abs( vuu )*eps, safmin )
793 END IF
794 END IF
795 END IF
796
797
798
799 lallwork = llwork
800
801 CALL pdsyntrd( uplo, n, a, ia, ja, desca, work( indd ),
802 $ work( inde ), work( indtau ), work( indwork ),
803 $ llwork, iinfo )
804
805
806
807
808
809
810
811
812 offset = 0
813 IF( ia.EQ.1 .AND. ja.EQ.1 .AND. rsrc_a.EQ.0 .AND. csrc_a.EQ.0 )
814 $ THEN
815 CALL pdlared1d( n, ia, ja, desca, work( indd ), work( indd2 ),
816 $ work( indwork ), llwork )
817
818 CALL pdlared1d( n, ia, ja, desca, work( inde ), work( inde2 ),
819 $ work( indwork ), llwork )
820 IF( .NOT.lower )
821 $ offset = 1
822 ELSE
823 DO 10 i = 1, n
824 CALL pdelget(
'A',
' ', work( indd2+i-1 ), a, i+ia-1,
825 $ i+ja-1, desca )
826 10 CONTINUE
827 IF(
lsame( uplo,
'U' ) )
THEN
828 DO 20 i = 1, n - 1
829 CALL pdelget(
'A',
' ', work( inde2+i-1 ), a, i+ia-1,
830 $ i+ja, desca )
831 20 CONTINUE
832 ELSE
833 DO 30 i = 1, n - 1
834 CALL pdelget(
'A',
' ', work( inde2+i-1 ), a, i+ia,
835 $ i+ja-1, desca )
836 30 CONTINUE
837 END IF
838 END IF
839
840
841
842 IF( wantz ) THEN
843 order = 'B'
844 ELSE
845 order = 'E'
846 END IF
847
848 CALL pdstebz( ictxt, range, order, n, vll, vuu, il, iu, abstll,
849 $ work( indd2 ), work( inde2+offset ), m, nsplit, w,
850 $ iwork( indibl ), iwork( indisp ), work( indwork ),
851 $ llwork, iwork( 1 ), isizestebz, iinfo )
852
853
854
855
856
857
858
859
860
861 IF( iinfo.NE.0 ) THEN
862 info = info + ierrebz
863 DO 40 i = 1, m
864 iwork( indibl+i-1 ) = abs( iwork( indibl+i-1 ) )
865 40 CONTINUE
866 END IF
867 IF( wantz ) THEN
868
869 IF( valeig ) THEN
870
871
872
873
874
875
876
877
878
879
880
881 CALL igamn2d( ictxt, 'A', ' ', 1, 1, lallwork, 1, 1, 1, -1,
882 $ -1, -1 )
883
884 maxeigs = descz( n_ )
885
886 DO 50 nz =
min( maxeigs, m ), 0, -1
887 mq0 =
numroc( nz, nb, 0, 0, npcol )
888 sizestein =
iceil( nz, nprocs )*n +
max( 5*n, np0*mq0 )
889 sizeormtr =
max( ( nb*( nb-1 ) ) / 2, ( mq0+np0 )*nb ) +
890 $ nb*nb
891
892 sizesyevx =
max( sizestein, sizeormtr )
893 IF( sizesyevx.LE.lallwork )
894 $ GO TO 60
895 50 CONTINUE
896 60 CONTINUE
897 ELSE
898 nz = m
899 END IF
901 IF( nz.NE.m ) THEN
902 info = info + ierrspc
903
904 DO 70 i = 1, m
905 ifail( i ) = 0
906 70 CONTINUE
907
908
909
910
911
912
913
914
915
916
917 IF( nsplit.GT.1 ) THEN
918 CALL dlasrt( 'I', m, w, iinfo )
919 nzz = 0
920 IF( nz.GT.0 ) THEN
921
922 vuu = w( nz ) - ten*( eps*anrm+safmin )
923 IF( vll.GE.vuu ) THEN
924 nzz = 0
925 ELSE
926 CALL pdstebz( ictxt, range, order, n, vll, vuu, il,
927 $ iu, abstll, work( indd2 ),
928 $ work( inde2+offset ), nzz, nsplit, w,
929 $ iwork( indibl ), iwork( indisp ),
930 $ work( indwork ), llwork, iwork( 1 ),
931 $ isizestebz, iinfo )
932 END IF
933
934 IF( mod( info / ierrebz, 1 ).EQ.0 ) THEN
935 IF( nzz.GT.nz .OR. iinfo.NE.0 ) THEN
936 info = info + ierrebz
937 END IF
938 END IF
939 END IF
941
942 END IF
943 END IF
944 CALL pdstein( n, work( indd2 ), work( inde2+offset ), nz, w,
945 $ iwork( indibl ), iwork( indisp ), orfac, z, iz,
946 $ jz, descz, work( indwork ), lallwork, iwork( 1 ),
947 $ isizestein, ifail, iclustr, gap, iinfo )
948
949 IF( iinfo.GE.nz+1 )
950 $ info = info + ierrcls
951 IF( mod( iinfo, nz+1 ).NE.0 )
952 $ info = info + ierrein
953
954
955
956
957 IF( nz.GT.0 ) THEN
958 CALL pdormtr(
'L', uplo,
'N', n, nz, a, ia, ja, desca,
959 $ work( indtau ), z, iz, jz, descz,
960 $ work( indwork ), llwork, iinfo )
961 END IF
962
963 END IF
964
965
966
967 IF( iscale.EQ.1 ) THEN
968 CALL dscal( m, one / sigma, w, 1 )
969 END IF
970
971 work( 1 ) = dble( lwopt )
972 iwork( 1 ) = liwmin
973
974 RETURN
975
976
977
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)
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)
double precision function pdlamch(ictxt, cmach)
subroutine pdelget(scope, top, alpha, a, ia, ja, desca)
double precision function pdlansy(norm, uplo, n, a, ia, ja, desca, work)
subroutine pdlared1d(n, ia, ja, desc, bycol, byall, work, lwork)
subroutine pdlascl(type, cfrom, cto, m, n, a, ia, ja, desca, info)
subroutine pdormtr(side, uplo, trans, m, n, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine pdstebz(ictxt, range, order, n, vl, vu, il, iu, abstol, d, e, m, nsplit, w, iblock, isplit, work, lwork, iwork, liwork, info)
subroutine pdstein(n, d, e, m, w, iblock, isplit, orfac, z, iz, jz, descz, work, lwork, iwork, liwork, ifail, iclustr, gap, info)
subroutine pdsyntrd(uplo, n, a, ia, ja, desca, d, e, tau, work, lwork, info)
integer function pjlaenv(ictxt, ispec, name, opts, n1, n2, n3, n4)
subroutine pxerbla(ictxt, srname, info)