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 REAL ABSTOL, ORFAC, VL, VU
17
18
19
20 INTEGER DESCA( * ), DESCB( * ), DESCZ( * ),
21 $ ICLUSTR( * ), IFAIL( * ), IWORK( * )
22 REAL 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 REAL ONE
495 parameter( one = 1.0e+0 )
496 REAL FIVE, ZERO
497 parameter( five = 5.0e+0, zero = 0.0e+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 REAL EPS, SCALE
510
511
512 INTEGER IDUM1( 5 ), IDUM2( 5 )
513
514
515 LOGICAL LSAME
516 INTEGER ICEIL, INDXG2P, NUMROC, PJLAENV
517 REAL PSLAMCH
519
520
523 $
pxerbla, sgebr2d, sgebs2d, sscal
524
525
526 INTRINSIC abs, dble, ichar, int,
max,
min, mod, real,
527 $ sqrt
528
529
530
531 IF( block_cyclic_2d*csrc_*ctxt_*dlen_*dtype_*lld_*mb_*m_*nb_*n_*
532 $ rsrc_.LT.0 )RETURN
533
534
535
536 ictxt = desca( ctxt_ )
537 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
538
539
540
541 info = 0
542 IF( nprow.EQ.-1 ) THEN
543 info = -( 900+ctxt_ )
544 ELSE IF( desca( ctxt_ ).NE.descb( ctxt_ ) ) THEN
545 info = -( 1300+ctxt_ )
546 ELSE IF( desca( ctxt_ ).NE.descz( ctxt_ ) ) THEN
547 info = -( 2600+ctxt_ )
548 ELSE
549
550
551
552 eps =
pslamch( desca( ctxt_ ),
'Precision' )
553
554 wantz =
lsame( jobz,
'V' )
555 upper =
lsame( uplo,
'U' )
556 alleig =
lsame( range,
'A' )
557 valeig =
lsame( range,
'V' )
558 indeig =
lsame( range,
'I' )
559 CALL chk1mat( n, 4, n, 4, ia, ja, desca, 9, info )
560 CALL chk1mat( n, 4, n, 4, ib, jb, descb, 13, info )
561 CALL chk1mat( n, 4, n, 4, iz, jz, descz, 26, info )
562 IF( info.EQ.0 ) THEN
563 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
564 work( 1 ) = abstol
565 IF( valeig ) THEN
566 work( 2 ) = vl
567 work( 3 ) = vu
568 ELSE
569 work( 2 ) = zero
570 work( 3 ) = zero
571 END IF
572 CALL sgebs2d( desca( ctxt_ ), 'ALL', ' ', 3, 1, work, 3 )
573 ELSE
574 CALL sgebr2d( desca( ctxt_ ), 'ALL', ' ', 3, 1, work, 3,
575 $ 0, 0 )
576 END IF
577 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
578 $ nprow )
579 ibrow =
indxg2p( ib, descb( mb_ ), myrow, descb( rsrc_ ),
580 $ nprow )
581 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
582 $ npcol )
583 ibcol =
indxg2p( jb, descb( nb_ ), mycol, descb( csrc_ ),
584 $ npcol )
585 iroffa = mod( ia-1, desca( mb_ ) )
586 icoffa = mod( ja-1, desca( nb_ ) )
587 iroffb = mod( ib-1, descb( mb_ ) )
588 icoffb = mod( jb-1, descb( nb_ ) )
589
590
591
592 lquery = .false.
593 IF( lwork.EQ.-1 .OR. liwork.EQ.-1 )
594 $ lquery = .true.
595
596 liwmin = 6*
max( n, ( nprow*npcol )+1, 4 )
597
598 nb = desca( mb_ )
600 np0 =
numroc( nn, nb, 0, 0, nprow )
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,
'PSSYTTRD',
'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 nb = desca( mb_ )
633 np0 =
numroc( n, nb, 0, 0, nprow )
634 nq0 =
numroc( n, nb, 0, 0, npcol )
635 nsygst_lwopt = 2*np0*nb + nq0*nb + nb*nb
636 lwopt =
max( lwopt, n+nsytrd_lwopt, nsygst_lwopt )
637
638
639
640 IF( ibtype.LT.1 .OR. ibtype.GT.3 ) THEN
641 info = -1
642 ELSE IF( .NOT.( wantz .OR.
lsame( jobz,
'N' ) ) )
THEN
643 info = -2
644 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
645 info = -3
646 ELSE IF( .NOT.upper .AND. .NOT.
lsame( uplo,
'L' ) )
THEN
647 info = -4
648 ELSE IF( n.LT.0 ) THEN
649 info = -5
650 ELSE IF( iroffa.NE.0 ) THEN
651 info = -7
652 ELSE IF( icoffa.NE.0 ) THEN
653 info = -8
654 ELSE IF( desca( mb_ ).NE.desca( nb_ ) ) THEN
655 info = -( 900+nb_ )
656 ELSE IF( desca( m_ ).NE.descb( m_ ) ) THEN
657 info = -( 1300+m_ )
658 ELSE IF( desca( n_ ).NE.descb( n_ ) ) THEN
659 info = -( 1300+n_ )
660 ELSE IF( desca( mb_ ).NE.descb( mb_ ) ) THEN
661 info = -( 1300+mb_ )
662 ELSE IF( desca( nb_ ).NE.descb( nb_ ) ) THEN
663 info = -( 1300+nb_ )
664 ELSE IF( desca( rsrc_ ).NE.descb( rsrc_ ) ) THEN
665 info = -( 1300+rsrc_ )
666 ELSE IF( desca( csrc_ ).NE.descb( csrc_ ) ) THEN
667 info = -( 1300+csrc_ )
668 ELSE IF( desca( ctxt_ ).NE.descb( ctxt_ ) ) THEN
669 info = -( 1300+ctxt_ )
670 ELSE IF( desca( m_ ).NE.descz( m_ ) ) THEN
671 info = -( 2200+m_ )
672 ELSE IF( desca( n_ ).NE.descz( n_ ) ) THEN
673 info = -( 2200+n_ )
674 ELSE IF( desca( mb_ ).NE.descz( mb_ ) ) THEN
675 info = -( 2200+mb_ )
676 ELSE IF( desca( nb_ ).NE.descz( nb_ ) ) THEN
677 info = -( 2200+nb_ )
678 ELSE IF( desca( rsrc_ ).NE.descz( rsrc_ ) ) THEN
679 info = -( 2200+rsrc_ )
680 ELSE IF( desca( csrc_ ).NE.descz( csrc_ ) ) THEN
681 info = -( 2200+csrc_ )
682 ELSE IF( desca( ctxt_ ).NE.descz( ctxt_ ) ) THEN
683 info = -( 2200+ctxt_ )
684 ELSE IF( iroffb.NE.0 .OR. ibrow.NE.iarow ) THEN
685 info = -11
686 ELSE IF( icoffb.NE.0 .OR. ibcol.NE.iacol ) THEN
687 info = -12
688 ELSE IF( valeig .AND. n.GT.0 .AND. vu.LE.vl ) THEN
689 info = -15
690 ELSE IF( indeig .AND. ( il.LT.1 .OR. il.GT.
max( 1, n ) ) )
691 $ THEN
692 info = -16
693 ELSE IF( indeig .AND. ( iu.LT.
min( n, il ) .OR. iu.GT.n ) )
694 $ THEN
695 info = -17
696 ELSE IF( valeig .AND. ( abs( work( 2 )-vl ).GT.five*eps*
697 $ abs( vl ) ) ) THEN
698 info = -14
699 ELSE IF( valeig .AND. ( abs( work( 3 )-vu ).GT.five*eps*
700 $ abs( vu ) ) ) THEN
701 info = -15
702 ELSE IF( abs( work( 1 )-abstol ).GT.five*eps*abs( abstol ) )
703 $ THEN
704 info = -18
705 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
706 info = -28
707 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
708 info = -30
709 END IF
710 END IF
711 idum1( 1 ) = ibtype
712 idum2( 1 ) = 1
713 IF( wantz ) THEN
714 idum1( 2 ) = ichar( 'V' )
715 ELSE
716 idum1( 2 ) = ichar( 'N' )
717 END IF
718 idum2( 2 ) = 2
719 IF( upper ) THEN
720 idum1( 3 ) = ichar( 'U' )
721 ELSE
722 idum1( 3 ) = ichar( 'L' )
723 END IF
724 idum2( 3 ) = 3
725 IF( alleig ) THEN
726 idum1( 4 ) = ichar( 'A' )
727 ELSE IF( indeig ) THEN
728 idum1( 4 ) = ichar( 'I' )
729 ELSE
730 idum1( 4 ) = ichar( 'V' )
731 END IF
732 idum2( 4 ) = 4
733 IF( lquery ) THEN
734 idum1( 5 ) = -1
735 ELSE
736 idum1( 5 ) = 1
737 END IF
738 idum2( 5 ) = 5
739 CALL pchk2mat( n, 4, n, 4, ia, ja, desca, 9, n, 4, n, 4, ib,
740 $ jb, descb, 13, 5, idum1, idum2, info )
741 CALL pchk1mat( n, 4, n, 4, iz, jz, descz, 26, 0, idum1, idum2,
742 $ info )
743 END IF
744
745 iwork( 1 ) = liwmin
746 work( 1 ) = real( lwopt )
747
748 IF( info.NE.0 ) THEN
749 CALL pxerbla( ictxt,
'PSSYGVX ', -info )
750 RETURN
751 ELSE IF( lquery ) THEN
752 RETURN
753 END IF
754
755
756
757 CALL pspotrf( uplo, n, b, ib, jb, descb, info )
758 IF( info.NE.0 ) THEN
759 iwork( 1 ) = liwmin
760 work( 1 ) = real( lwopt )
761 ifail( 1 ) = info
762 info = ierrnpd
763 RETURN
764 END IF
765
766
767
768 CALL pssyngst( ibtype, uplo, n, a, ia, ja, desca, b, ib, jb,
769 $ descb, scale, work, lwork, info )
770 CALL pssyevx( jobz, range, uplo, n, a, ia, ja, desca, vl, vu, il,
771 $ iu, abstol, m, nz, w, orfac, z, iz, jz, descz, work,
772 $ lwork, iwork, liwork, ifail, iclustr, gap, info )
773
774 IF( wantz ) THEN
775
776
777
778 neig = m
779 IF( ibtype.EQ.1 .OR. ibtype.EQ.2 ) THEN
780
781
782
783
784
785 IF( upper ) THEN
786 trans = 'N'
787 ELSE
788 trans = 'T'
789 END IF
790
791 CALL pstrsm( 'Left', uplo, trans, 'Non-unit', n, neig, one,
792 $ b, ib, jb, descb, z, iz, jz, descz )
793
794 ELSE IF( ibtype.EQ.3 ) THEN
795
796
797
798
799 IF( upper ) THEN
800 trans = 'T'
801 ELSE
802 trans = 'N'
803 END IF
804
805 CALL pstrmm( 'Left', uplo, trans, 'Non-unit', n, neig, one,
806 $ b, ib, jb, descb, z, iz, jz, descz )
807 END IF
808 END IF
809
810 IF( scale.NE.one ) THEN
811 CALL sscal( n, scale, w, 1 )
812 END IF
813
814 iwork( 1 ) = liwmin
815 work( 1 ) = real( lwopt )
816 RETURN
817
818
819
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 pspotrf(uplo, n, a, ia, ja, desca, info)
subroutine pssyevx(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 pssyngst(ibtype, uplo, n, a, ia, ja, desca, b, ib, jb, descb, scale, work, lwork, info)
subroutine pxerbla(ictxt, srname, info)