6
7
8
9
10
11
12
13 CHARACTER JOBZ, RANGE, UPLO
14 INTEGER IA, IB, IBTYPE, IL, INFO, IU, IZ, JA, JB, JZ,
15 $ LIWORK, LRWORK, LWORK, M, N, NZ
16 REAL ABSTOL, ORFAC, VL, VU
17
18
19
20 INTEGER DESCA( * ), DESCB( * ), DESCZ( * ),
21 $ ICLUSTR( * ), IFAIL( * ), IWORK( * )
22 REAL GAP( * ), RWORK( * ), W( * )
23 COMPLEX A( * ), B( * ), WORK( * ), Z( * )
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
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494 INTEGER BLOCK_CYCLIC_2D, DLEN_, DTYPE_, CTXT_, M_, N_,
495 $ MB_, NB_, RSRC_, CSRC_, LLD_
496 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
497 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
498 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
499 COMPLEX ONE
500 parameter( one = 1.0e+0 )
501 REAL FIVE, ZERO
502 parameter( five = 5.0e+0, zero = 0.0e+0 )
503 INTEGER IERRNPD
504 parameter( ierrnpd = 16 )
505
506
507 LOGICAL ALLEIG, INDEIG, LQUERY, UPPER, VALEIG, WANTZ
508 CHARACTER TRANS
509 INTEGER ANB, IACOL, IAROW, IBCOL, IBROW, ICOFFA,
510 $ ICOFFB, ICTXT, IROFFA, IROFFB, LIWMIN, LRWMIN,
511 $ LRWOPT, LWMIN, LWOPT, MQ0, MYCOL, MYROW, NB,
512 $ NEIG, NHEGST_LWOPT, NHETRD_LWOPT, NN, NP0,
513 $ NPCOL, NPROW, NPS, NQ0, SQNPC
514 REAL EPS, SCALE
515
516
517 INTEGER IDUM1( 5 ), IDUM2( 5 )
518
519
520 LOGICAL LSAME
521 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
522 REAL PSLAMCH
524
525
528 $
pxerbla, sgebr2d, sgebs2d, sscal
529
530
531 INTRINSIC abs,
cmplx, dble, ichar, int,
max,
min, mod,
532 $ real, sqrt
533
534
535
536 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
537 $ rsrc_.LT.0 )RETURN
538
539
540
541 ictxt = desca( ctxt_ )
542 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
543
544
545
546 info = 0
547 IF( nprow.EQ.-1 ) THEN
548 info = -( 900+ctxt_ )
549 ELSE IF( desca( ctxt_ ).NE.descb( ctxt_ ) ) THEN
550 info = -( 1300+ctxt_ )
551 ELSE IF( desca( ctxt_ ).NE.descz( ctxt_ ) ) THEN
552 info = -( 2600+ctxt_ )
553 ELSE
554
555
556
557 eps =
pslamch( desca( ctxt_ ),
'Precision' )
558
559 wantz =
lsame( jobz,
'V' )
560 upper =
lsame( uplo,
'U' )
561 alleig =
lsame( range,
'A' )
562 valeig =
lsame( range,
'V' )
563 indeig =
lsame( range,
'I' )
564 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 9, info )
565 CALL chk1mat( n, 4, n, 4, ib, jb, descb, 13, info )
566 CALL chk1mat( n, 4, n, 4, iz, jz, descz, 26, info )
567 IF( info.EQ.0 ) THEN
568 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
569 rwork( 1 ) = abstol
570 IF( valeig ) THEN
571 rwork( 2 ) = vl
572 rwork( 3 ) = vu
573 ELSE
574 rwork( 2 ) = zero
575 rwork( 3 ) = zero
576 END IF
577 CALL sgebs2d( desca( ctxt_ ), 'ALL', ' ', 3, 1, rwork,
578 $ 3 )
579 ELSE
580 CALL sgebr2d( desca( ctxt_ ), 'ALL', ' ', 3, 1, rwork, 3,
581 $ 0, 0 )
582 END IF
583 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
584 $ nprow )
585 ibrow =
indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
586 $ nprow )
587 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
588 $ npcol )
589 ibcol =
indxg2p( jb, descb( nb_ ), mycol, descb( csrc_ ),
590 $ npcol )
591 iroffa = mod( ia-1, desca( mb_ ) )
592 icoffa = mod( ja-1, desca( nb_ ) )
593 iroffb = mod( ib-1, descb( mb_ ) )
594 icoffb = mod( jb-1, descb( nb_ ) )
595
596
597
598 lquery = .false.
599 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 .OR. lrwork.EQ.-1 )
600 $ lquery = .true.
601
602 liwmin = 6*
max( n, ( nprow*npcol )+1, 4 )
603
604 nb = desca( mb_ )
606 np0 =
numroc( nn, nb, 0, 0, nprow )
607
608 IF( ( .NOT.wantz ) .OR. ( valeig .AND. ( .NOT.lquery ) ) )
609 $ THEN
610 lwmin = n +
max( nb*( np0+1 ), 3 )
611 lwopt = lwmin
612 lrwmin = 5*nn + 4*n
613 IF( wantz ) THEN
614 mq0 =
numroc(
max( n, nb, 2 ), nb, 0, 0, npcol )
615 lrwopt = 4*n +
max( 5*nn, np0*mq0 )
616 ELSE
617 lrwopt = lrwmin
618 END IF
619 neig = 0
620 ELSE
621 IF( alleig .OR. valeig ) THEN
622 neig = n
623 ELSE IF( indeig ) THEN
624 neig = iu - il + 1
625 END IF
626 mq0 =
numroc(
max( neig, nb, 2 ), nb, 0, 0, npcol )
627 lwmin = n + ( np0+mq0+nb )*nb
628 lwopt = lwmin
629 lrwmin = 4*n +
max( 5*nn, np0*mq0 ) +
630 $
iceil( neig, nprow*npcol )*nn
631 lrwopt = lrwmin
632
633 END IF
634
635
636
637
638 anb =
pjlaenv( ictxt, 3,
'PCHETTRD',
'L', 0, 0, 0, 0 )
639 sqnpc = int( sqrt( dble( nprow*npcol ) ) )
640 nps =
max(
numroc( n, 1, 0, 0, sqnpc ), 2*anb )
641 nhetrd_lwopt = 2*( anb+1 )*( 4*nps+2 ) + ( nps+4 )*nps
642 nb = desca( mb_ )
643 np0 =
numroc( n, nb, 0, 0, nprow )
644 nq0 =
numroc( n, nb, 0, 0, npcol )
645 nhegst_lwopt = 2*np0*nb + nq0*nb + nb*nb
646 lwopt =
max( lwopt, n+nhetrd_lwopt, nhegst_lwopt )
647
648
649
650 IF( ibtype.LT.1 .OR. ibtype.GT.3 ) THEN
651 info = -1
652 ELSE IF( .NOT.( wantz .OR.
lsame( jobz,
'N' ) ) )
THEN
653 info = -2
654 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
655 info = -3
656 ELSE IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
657 info = -4
658 ELSE IF( n.LT.0 ) THEN
659 info = -5
660 ELSE IF( iroffa.NE.0 ) THEN
661 info = -7
662 ELSE IF( icoffa.NE.0 ) THEN
663 info = -8
664 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
665 info = -( 900+nb_ )
666 ELSE IF( desca( m_ ).NE.descb( m_ ) ) THEN
667 info = -( 1300+m_ )
668 ELSE IF( desca( n_ ).NE.descb( n_ ) ) THEN
669 info = -( 1300+n_ )
670 ELSE IF( desca( mb_ ).NE.descb( mb_ ) ) THEN
671 info = -( 1300+mb_ )
672 ELSE IF( desca( nb_ ).NE.descb( nb_ ) ) THEN
673 info = -( 1300+nb_ )
674 ELSE IF( desca( rsrc_ ).NE.descb( rsrc_ ) ) THEN
675 info = -( 1300+rsrc_ )
676 ELSE IF( desca( csrc_ ).NE.descb( csrc_ ) ) THEN
677 info = -( 1300+csrc_ )
678 ELSE IF( desca( ctxt_ ).NE.descb( ctxt_ ) ) THEN
679 info = -( 1300+ctxt_ )
680 ELSE IF( desca( m_ ).NE.descz( m_ ) ) THEN
681 info = -( 2200+m_ )
682 ELSE IF( desca( n_ ).NE.descz( n_ ) ) THEN
683 info = -( 2200+n_ )
684 ELSE IF( desca( mb_ ).NE.descz( mb_ ) ) THEN
685 info = -( 2200+mb_ )
686 ELSE IF( desca( nb_ ).NE.descz( nb_ ) ) THEN
687 info = -( 2200+nb_ )
688 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) ) THEN
689 info = -( 2200+rsrc_ )
690 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) ) THEN
691 info = -( 2200+csrc_ )
692 ELSE IF( desca( ctxt_ ).NE.descz( ctxt_ ) ) THEN
693 info = -( 2200+ctxt_ )
694 ELSE IF( iroffb.NE.0 .OR. ibrow.NE.iarow ) THEN
695 info = -11
696 ELSE IF( icoffb.NE.0 .OR. ibcol.NE.iacol ) THEN
697 info = -12
698 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl ) THEN
699 info = -15
700 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
701 $ THEN
702 info = -16
703 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
704 $ THEN
705 info = -17
706 ELSE IF( valeig .AND. ( abs( rwork( 2 )-vl ).GT.five*eps*
707 $ abs( vl ) ) ) THEN
708 info = -14
709 ELSE IF( valeig .AND. ( abs( rwork( 3 )-vu ).GT.five*eps*
710 $ abs( vu ) ) ) THEN
711 info = -15
712 ELSE IF( abs( rwork( 1 )-abstol ).GT.five*eps*
713 $ abs( abstol ) ) THEN
714 info = -18
715 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
716 info = -28
717 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) THEN
718 info = -30
719 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
720 info = -32
721 END IF
722 END IF
723 idum1( 1 ) = ibtype
724 idum2( 1 ) = 1
725 IF( wantz ) THEN
726 idum1( 2 ) = ichar( 'V' )
727 ELSE
728 idum1( 2 ) = ichar( 'N' )
729 END IF
730 idum2( 2 ) = 2
731 IF( upper ) THEN
732 idum1( 3 ) = ichar( 'U' )
733 ELSE
734 idum1( 3 ) = ichar( 'L' )
735 END IF
736 idum2( 3 ) = 3
737 IF( alleig ) THEN
738 idum1( 4 ) = ichar( 'A' )
739 ELSE IF( indeig ) THEN
740 idum1( 4 ) = ichar( 'I' )
741 ELSE
742 idum1( 4 ) = ichar( 'V' )
743 END IF
744 idum2( 4 ) = 4
745 IF( lquery ) THEN
746 idum1( 5 ) = -1
747 ELSE
748 idum1( 5 ) = 1
749 END IF
750 idum2( 5 ) = 5
751 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 9, n, 4, n, 4, ib,
752 $ jb, descb, 13, 5, idum1, idum2, info )
753 CALL pchk1mat( n, 4, n, 4, iz, jz, descz, 26, 0, idum1, idum2,
754 $ info )
755 END IF
756
757 iwork( 1 ) = liwmin
758 work( 1 ) =
cmplx( real( lwopt ) )
759 rwork( 1 ) = real( lrwopt )
760
761 IF( info.NE.0 ) THEN
762 CALL pxerbla( ictxt,
'PCHEGVX ', -info )
763 RETURN
764 ELSE IF( lquery ) THEN
765 RETURN
766 END IF
767
768
769
770 CALL pcpotrf( uplo, n, b, ib, jb, descb, info )
771 IF( info.NE.0 ) THEN
772 iwork( 1 ) = liwmin
773 work( 1 ) =
cmplx( real( lwopt ) )
774 rwork( 1 ) = real( lrwopt )
775 ifail( 1 ) = info
776 info = ierrnpd
777 RETURN
778 END IF
779
780
781
782 CALL pchengst( ibtype, uplo, n, a, ia, ja, desca, b, ib, jb,
783 $ descb, scale, work, lwork, info )
784 CALL pcheevx( jobz, range, uplo, n, a, ia, ja, desca, vl, vu, il,
785 $ iu, abstol, m, nz, w, orfac, z, iz, jz, descz, work,
786 $ lwork, rwork, lrwork, iwork, liwork, ifail, iclustr,
787 $ gap, info )
788
789 IF( wantz ) THEN
790
791
792
793 neig = m
794 IF( ibtype.EQ.1 .OR. ibtype.EQ.2 ) THEN
795
796
797
798
799
800 IF( upper ) THEN
801 trans = 'N'
802 ELSE
803 trans = 'C'
804 END IF
805
806 CALL pctrsm( 'Left', uplo, trans, 'Non-unit', n, neig, one,
807 $ b, ib, jb, descb, z, iz, jz, descz )
808
809 ELSE IF( ibtype.EQ.3 ) THEN
810
811
812
813
814 IF( upper ) THEN
815 trans = 'C'
816 ELSE
817 trans = 'N'
818 END IF
819
820 CALL pctrmm( 'Left', uplo, trans, 'Non-unit', n, neig, one,
821 $ b, ib, jb, descb, z, iz, jz, descz )
822 END IF
823 END IF
824
825 IF( scale.NE.one ) THEN
826 CALL sscal( n, scale, w, 1 )
827 END IF
828
829 iwork( 1 ) = liwmin
830 work( 1 ) =
cmplx( real( lwopt ) )
831 rwork( 1 ) = real( lrwopt )
832 RETURN
833
834
835
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 pcheevx(jobz, range, uplo, n, a, ia, ja, desca, vl, vu, il, iu, abstol, m, nz, w, orfac, z, iz, jz, descz, work, lwork, rwork, lrwork, iwork, liwork, ifail, iclustr, gap, info)
subroutine pchengst(ibtype, uplo, n, a, ia, ja, desca, b, ib, jb, descb, scale, work, lwork, info)
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)
subroutine pcpotrf(uplo, n, a, ia, ja, desca, info)
integer function pjlaenv(ictxt, ispec, name, opts, n1, n2, n3, n4)
subroutine pxerbla(ictxt, srname, info)