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