6
7
8
9
10
11
12
13
14
15 IMPLICIT NONE
16
17
18 INTEGER IHIZ, ILOZ, KBOT, KTOP, LWORK, N, ND, NH, NS,
19 $ NV, NW, LIWORK, RECLEVEL
20 LOGICAL WANTT, WANTZ
21
22
23 INTEGER DESCH( * ), DESCZ( * ), DESCT( * ), DESCV( * ),
24 $ DESCW( * ), IWORK( * )
25 REAL H( * ), SI( KBOT ), SR( KBOT ), T( * ),
26 $ V( * ), WORK( * ), WV( * ),
27 $ Z( * )
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
232 $ LLD_, MB_, M_, NB_, N_, RSRC_
233 INTEGER RECMAX
234 LOGICAL SORTGRAD
235 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
236 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
237 $ rsrc_ = 7, csrc_ = 8, lld_ = 9, recmax = 3,
238 $ sortgrad = .false. )
239 REAL ZERO, ONE
240 parameter( zero = 0.0, one = 1.0 )
241
242
243 REAL AA, BB, BETA, CC, CS, DD, EVI, EVK, FOO, S,
244 $ SAFMAX, SAFMIN, SMLNUM, SN, TAU, ULP,
245 $ ELEM, ELEM1, ELEM2, ELEM3, R1, ANORM, RNORM,
246 $ RESAED
247 INTEGER I, IFST, ILST, INFO, INFQR, J, JW, K, KCOL,
248 $ KEND, KLN, KROW, KWTOP, LTOP, LWK1, LWK2, LWK3,
249 $ LWKOPT, NMIN, LLDH, LLDZ, LLDT, LLDV, LLDWV,
250 $ ICTXT, NPROW, NMAX, NPCOL, MYROW, MYCOL, NB,
251 $ IROFFH, M, RCOLS, TAUROWS, RROWS, TAUCOLS,
252 $ ITAU, IR, IPW, NPROCS, MLOC, IROFFHH,
253 $ ICOFFHH, HHRSRC, HHCSRC, HHROWS, HHCOLS,
254 $ IROFFZZ, ICOFFZZ, ZZRSRC, ZZCSRC, ZZROWS,
255 $ ZZCOLS, IERR, TZROWS0, TZCOLS0, IERR0, IPT0,
256 $ IPZ0, IPW0, NB2, ROUND, LILST, KK, LILST0,
257 $ IWRK1, RSRC, CSRC, LWK4, LWK5, IWRK2, LWK6,
258 $ LWK7, LWK8, ILWKOPT, TZROWS, TZCOLS, NSEL,
259 $ NPMIN, ICTXT_NEW, MYROW_NEW, MYCOL_NEW
260 LOGICAL BULGE, SORTED, LQUERY
261
262
263 INTEGER PAR( 6 ), DESCR( DLEN_ ),
264 $ DESCTAU( DLEN_ ), DESCHH( DLEN_ ),
265 $ DESCZZ( DLEN_ ), DESCTZ0( DLEN_ ),
266 $ PMAP( 64*64 )
267 REAL DDUM( 1 )
268
269
270 REAL SLAMCH, PSLANGE
271 INTEGER PILAENVX, NUMROC, INDXG2P, ICEIL, BLACS_PNUM
274
275
279 $
pslamve, blacs_gridinfo, blacs_gridmap,
280 $ blacs_gridexit, psgemr2d
281
282
283 INTRINSIC abs, float, int,
max,
min, sqrt
284
285
286 ictxt = desch( ctxt_ )
287 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
288 nprocs = nprow*npcol
289
290
291
292
293 lldh = desch( lld_ )
294 lldz = descz( lld_ )
295 lldt = desct( lld_ )
296 lldv = descv( lld_ )
297 lldwv = descw( lld_ )
298 nb = desch( mb_ )
299 iroffh = mod( ktop - 1, nb )
300 jw =
min( nw, kbot-ktop+1 )
301 nsel = nb+jw
302
303
304
305 par(1) =
pilaenvx(ictxt, 17,
'PSLAQR3',
'SV', jw, nb, -1, -1)
306 par(2) =
pilaenvx(ictxt, 18,
'PSLAQR3',
'SV', jw, nb, -1, -1)
307 par(3) =
pilaenvx(ictxt, 19,
'PSLAQR3',
'SV', jw, nb, -1, -1)
308 par(4) =
pilaenvx(ictxt, 20,
'PSLAQR3',
'SV', jw, nb, -1, -1)
309 par(5) =
pilaenvx(ictxt, 21,
'PSLAQR3',
'SV', jw, nb, -1, -1)
310 par(6) =
pilaenvx(ictxt, 22,
'PSLAQR3',
'SV', jw, nb, -1, -1)
311
312
313
314 lquery = lwork.EQ.-1 .OR. liwork.EQ.-1
315
316
317
318 IF( jw.LE.2 ) THEN
319 lwkopt = 1
320 ELSE
321
322
323
324 taurows =
numroc( 1, 1, mycol, descv(rsrc_), nprow )
325 taucols =
numroc( jw+iroffh, nb, mycol, descv(csrc_),
326 $ npcol )
327 CALL psgehrd( jw, 1, jw, t, 1, 1, desct, work, work, -1,
328 $ info )
329 lwk1 = int( work( 1 ) ) + taurows*taucols
330
331
332
333 CALL psormhr(
'Right',
'No', jw, jw, 1, jw, t, 1, 1, desct,
334 $ work, v, 1, 1, descv, work, -1, info )
335 lwk2 = int( work( 1 ) )
336
337
338
339 nmin =
pilaenvx( ictxt, 12,
'PSLAQR3',
'SV', jw, 1, jw, lwork )
340 nmax = ( n-1 ) / 3
341 IF( jw+iroffh.GT.nmin .AND. jw+iroffh.LE.nmax
342 $ .AND. reclevel.LT.recmax ) THEN
343 CALL pslaqr0( .true., .true., jw+iroffh, 1+iroffh,
344 $ jw+iroffh, t, desct, sr, si, 1, jw, v, descv,
345 $ work, -1, iwork, liwork-nsel, infqr,
346 $ reclevel+1 )
347 lwk3 = int( work( 1 ) )
348 iwrk1 = iwork( 1 )
349 ELSE
350 rsrc = desct( rsrc_ )
351 csrc = desct( csrc_ )
352 desct( rsrc_ ) = 0
353 desct( csrc_ ) = 0
354 CALL pslaqr1( .true., .true., jw+iroffh, 1, jw+iroffh, t,
355 $ desct, sr, si, 1, jw+iroffh, v, descv, work, -1,
356 $ iwork, liwork-nsel, infqr )
357 desct( rsrc_ ) = rsrc
358 desct( csrc_ ) = csrc
359 lwk3 = int( work( 1 ) )
360 iwrk1 = iwork( 1 )
361 END IF
362
363
364
365 tzrows0 =
numroc( jw+iroffh, nb, myrow, 0, nprow )
366 tzcols0 =
numroc( jw+iroffh, nb, mycol, 0, npcol )
367 lwk4 = 2 * tzrows0*tzcols0
368
369
370
371 CALL pstrord(
'Vectors', iwork, par, jw+iroffh, t, 1, 1,
372 $ desct, v, 1, 1, descv, ddum, ddum, mloc, work, -1,
373 $ iwork, liwork-nsel, info )
374 lwk5 = int( work( 1 ) )
375 iwrk2 = iwork( 1 )
376
377
378
379
380 rrows =
numroc( n+iroffh, nb, myrow, descv(rsrc_), nprow )
381 rcols =
numroc( 1, 1, mycol, descv(csrc_), npcol )
382 lwk6 = rrows*rcols + taurows*taucols +
385
386
387
388
395
396
397
398 tzrows =
numroc( jw+iroffh, nb, myrow, desct(rsrc_), nprow )
399 tzcols =
numroc( jw+iroffh, nb, mycol, desct(csrc_), npcol )
400 lwk8 = 2*tzrows*tzcols
401
402
403
404 lwkopt =
max( lwk1, lwk2, lwk3+lwk4, lwk5, lwk6, lwk7, lwk8 )
405 ilwkopt =
max( iwrk1, iwrk2 )
406 END IF
407
408
409
410 work( 1 ) = float( lwkopt )
411
412
413
414 iwork( 1 ) = ilwkopt + nsel
415 IF( lquery )
416 $ RETURN
417
418
419 ns = 0
420 nd = 0
421 IF( ktop.GT.kbot )
422 $ RETURN
423
424
425 IF( nw.LT.1 )
426 $ RETURN
427
428
429
430 safmin =
slamch(
'SAFE MINIMUM' )
431 safmax = one / safmin
432 CALL slabad( safmin, safmax )
433 ulp =
slamch(
'PRECISION' )
434 smlnum = safmin*( float( n ) / ulp )
435
436
437
438 jw =
min( nw, kbot-ktop+1 )
439 kwtop = kbot - jw + 1
440 IF( kwtop.EQ.ktop ) THEN
441 s = zero
442 ELSE
443 CALL pselget(
'All',
'1-Tree', s, h, kwtop, kwtop-1, desch )
444 END IF
445
446 IF( kbot.EQ.kwtop ) THEN
447
448
449
450 CALL pselget(
'All',
'1-Tree', sr( kwtop ), h, kwtop, kwtop,
451 $ desch )
452 si( kwtop ) = zero
453 ns = 1
454 nd = 0
455 IF( abs( s ).LE.
max( smlnum, ulp*abs( sr( kwtop ) ) ) )
456 $ THEN
457 ns = 0
458 nd = 1
459 IF( kwtop.GT.ktop )
460 $
CALL pselset( h, kwtop, kwtop-1 , desch, zero )
461 END IF
462 RETURN
463 END IF
464
465 IF( kwtop.EQ.ktop .AND. kbot-kwtop.EQ.1 ) THEN
466
467
468
469 CALL pselget(
'All',
'1-Tree', aa, h, kwtop, kwtop, desch )
470 CALL pselget(
'All',
'1-Tree', bb, h, kwtop, kwtop+1, desch )
471 CALL pselget(
'All',
'1-Tree', cc, h, kwtop+1, kwtop, desch )
472 CALL pselget(
'All',
'1-Tree', dd, h, kwtop+1, kwtop+1, desch )
473 CALL slanv2( aa, bb, cc, dd, sr(kwtop), si(kwtop),
474 $ sr(kwtop+1), si(kwtop+1), cs, sn )
475 ns = 0
476 nd = 2
477 IF( cc.EQ.zero ) THEN
478 i = kwtop
479 IF( i+2.LE.n .AND. wantt )
480 $
CALL psrot( n-i-1, h, i, i+2, desch, desch(m_), h, i+1,
481 $ i+2, desch, desch(m_), cs, sn, work, lwork, info )
482 IF( i.GT.1 )
483 $
CALL psrot( i-1, h, 1, i, desch, 1, h, 1, i+1, desch, 1,
484 $ cs, sn, work, lwork, info )
485 IF( wantz )
486 $
CALL psrot( ihiz-iloz+1, z, iloz, i, descz, 1, z, iloz,
487 $ i+1, descz, 1, cs, sn, work, lwork, info )
488 CALL pselset( h, i, i, desch, aa )
489 CALL pselset( h, i, i+1, desch, bb )
490 CALL pselset( h, i+1, i, desch, cc )
491 CALL pselset( h, i+1, i+1, desch, dd )
492 END IF
493 work( 1 ) = float( lwkopt )
494 RETURN
495 END IF
496
497
498
499
500 iroffh = mod( kwtop - 1, nb )
501
502
503
504
505 desct( m_ ) = jw+iroffh
506 desct( n_ ) = jw+iroffh
507
508
509
510
511
512
513
514
515 CALL pslaset(
'All', iroffh, jw+iroffh, zero, one, t, 1, 1,
516 $ desct )
517 CALL pslaset(
'All', jw, iroffh, zero, zero, t, 1+iroffh, 1,
518 $ desct )
519 CALL pslacpy(
'All', 1, jw, h, kwtop, kwtop, desch, t, 1+iroffh,
520 $ 1+iroffh, desct )
521 CALL pslacpy(
'Upper', jw-1, jw-1, h, kwtop+1, kwtop, desch, t,
522 $ 1+iroffh+1, 1+iroffh, desct )
523 IF( jw.GT.2 )
524 $
CALL pslaset(
'Lower', jw-2, jw-2, zero, zero, t, 1+iroffh+2,
525 $ 1+iroffh, desct )
526 CALL pslacpy(
'All', jw-1, 1, h, kwtop+1, kwtop+jw-1, desch, t,
527 $ 1+iroffh+1, 1+iroffh+jw-1, desct )
528
529
530
531 CALL pslaset(
'All', jw+iroffh, jw+iroffh, zero, one, v, 1, 1,
532 $ descv )
533
534
535
536 npmin =
pilaenvx( ictxt, 23,
'PSLAQR3',
'SV', jw, nb, nprow,
537 $ npcol )
538 nmin =
pilaenvx( ictxt, 12,
'PSLAQR3',
'SV', jw, 1, jw, lwork )
539 nmax = ( n-1 ) / 3
540 IF(
min(nprow, npcol).LE.npmin+1 .OR. reclevel.GE.1 )
THEN
541
542
543
544
545 IF( jw+iroffh.GT.nmin .AND. jw+iroffh.LE.nmax
546 $ .AND. reclevel.LT.recmax ) THEN
547 CALL pslaqr0( .true., .true., jw+iroffh, 1+iroffh,
548 $ jw+iroffh, t, desct, sr( kwtop-iroffh ),
549 $ si( kwtop-iroffh ), 1+iroffh, jw+iroffh, v, descv,
550 $ work, lwork, iwork(nsel+1), liwork-nsel, infqr,
551 $ reclevel+1 )
552 ELSE
553 IF( desct(rsrc_).EQ.0 .AND. desct(csrc_).EQ.0 ) THEN
554 IF( jw+iroffh.GT.desct( mb_ ) ) THEN
555 CALL pslaqr1( .true., .true., jw+iroffh, 1,
556 $ jw+iroffh, t, desct, sr( kwtop-iroffh ),
557 $ si( kwtop-iroffh ), 1, jw+iroffh, v,
558 $ descv, work, lwork, iwork(nsel+1), liwork-nsel,
559 $ infqr )
560 ELSE
561 IF( myrow.EQ.0 .AND. mycol.EQ.0 ) THEN
562 CALL slahqr( .true., .true., jw+iroffh, 1+iroffh,
563 $ jw+iroffh, t, desct(lld_),
564 $ sr( kwtop-iroffh ), si( kwtop-iroffh ),
565 $ 1+iroffh, jw+iroffh, v, descv(lld_), infqr )
566 ELSE
567 infqr = 0
568 END IF
569 IF( nprocs.GT.1 )
570 $ CALL igamn2d( ictxt, 'All', '1-Tree', 1, 1, infqr,
571 $ 1, -1, -1, -1, -1, -1 )
572 END IF
573 ELSEIF( jw+iroffh.LE.desct( mb_ ) ) THEN
574 IF( myrow.EQ.desct(rsrc_) .AND. mycol.EQ.desct(csrc_) )
575 $ THEN
576 CALL slahqr( .true., .true., jw+iroffh, 1+iroffh,
577 $ jw+iroffh, t, desct(lld_),
578 $ sr( kwtop-iroffh ), si( kwtop-iroffh ),
579 $ 1+iroffh, jw+iroffh, v, descv(lld_), infqr )
580 ELSE
581 infqr = 0
582 END IF
583 IF( nprocs.GT.1 )
584 $ CALL igamn2d( ictxt, 'All', '1-Tree', 1, 1, infqr,
585 $ 1, -1, -1, -1, -1, -1 )
586 ELSE
587 tzrows0 =
numroc( jw+iroffh, nb, myrow, 0, nprow )
588 tzcols0 =
numroc( jw+iroffh, nb, mycol, 0, npcol )
589 CALL descinit( desctz0, jw+iroffh, jw+iroffh, nb, nb, 0,
590 $ 0, ictxt,
max(1,tzrows0), ierr0 )
591 ipt0 = 1
592 ipz0 = ipt0 +
max(1,tzrows0)*tzcols0
593 ipw0 = ipz0 +
max(1,tzrows0)*tzcols0
594 CALL pslamve(
'All', jw+iroffh, jw+iroffh, t, 1, 1,
595 $ desct, work(ipt0), 1, 1, desctz0, work(ipw0) )
596 CALL pslaset(
'All', jw+iroffh, jw+iroffh, zero, one,
597 $ work(ipz0), 1, 1, desctz0 )
598 CALL pslaqr1( .true., .true., jw+iroffh, 1,
599 $ jw+iroffh, work(ipt0), desctz0,
600 $ sr( kwtop-iroffh ), si( kwtop-iroffh ),
601 $ 1, jw+iroffh, work(ipz0),
602 $ desctz0, work(ipw0), lwork-ipw0+1, iwork(nsel+1),
603 $ liwork-nsel, infqr )
604 CALL pslamve(
'All', jw+iroffh, jw+iroffh, work(ipt0), 1,
605 $ 1, desctz0, t, 1, 1, desct, work(ipw0) )
606 CALL pslamve(
'All', jw+iroffh, jw+iroffh, work(ipz0), 1,
607 $ 1, desctz0, v, 1, 1, descv, work(ipw0) )
608 END IF
609 END IF
610 ELSE
611
612
613
614
615
616 ictxt_new = ictxt
617 DO 20 i = 0, npmin-1
618 DO 10 j = 0, npmin-1
619 pmap( j+1+i*npmin ) = blacs_pnum( ictxt, i, j )
620 10 CONTINUE
621 20 CONTINUE
622 CALL blacs_gridmap( ictxt_new, pmap, npmin, npmin, npmin )
623 CALL blacs_gridinfo( ictxt_new, npmin, npmin, myrow_new,
624 $ mycol_new )
625 IF( myrow.GE.npmin .OR. mycol.GE.npmin ) ictxt_new = -1
626 IF( ictxt_new.GE.0 ) THEN
627 tzrows0 =
numroc( jw, nb, myrow_new, 0, npmin )
628 tzcols0 =
numroc( jw, nb, mycol_new, 0, npmin )
629 CALL descinit( desctz0, jw, jw, nb, nb, 0,
630 $ 0, ictxt_new,
max(1,tzrows0), ierr0 )
631 ipt0 = 1
632 ipz0 = ipt0 +
max(1,tzrows0)*
max(1,tzcols0)
633 ipw0 = ipz0 +
max(1,tzrows0)*
max(1,tzcols0)
634 ELSE
635 ipt0 = 1
636 ipz0 = 2
637 ipw0 = 3
638 desctz0( ctxt_ ) = -1
639 infqr = 0
640 END IF
641 CALL psgemr2d( jw, jw, t, 1+iroffh, 1+iroffh, desct,
642 $ work(ipt0), 1, 1, desctz0, ictxt )
643 IF( ictxt_new.GE.0 ) THEN
644 CALL pslaset(
'All', jw, jw, zero, one, work(ipz0), 1, 1,
645 $ desctz0 )
646 nmin =
pilaenvx( ictxt_new, 12,
'PSLAQR3',
'SV', jw, 1, jw,
647 $ lwork )
648 IF( jw.GT.nmin .AND. jw.LE.nmax .AND. reclevel.LT.1 ) THEN
649 CALL pslaqr0( .true., .true., jw, 1, jw, work(ipt0),
650 $ desctz0, sr( kwtop ), si( kwtop ), 1, jw,
651 $ work(ipz0), desctz0, work(ipw0), lwork-ipw0+1,
652 $ iwork(nsel+1), liwork-nsel, infqr,
653 $ reclevel+1 )
654 ELSE
655 CALL pslaqr1( .true., .true., jw, 1, jw, work(ipt0),
656 $ desctz0, sr( kwtop ), si( kwtop ), 1, jw,
657 $ work(ipz0), desctz0, work(ipw0), lwork-ipw0+1,
658 $ iwork(nsel+1), liwork-nsel, infqr )
659 END IF
660 END IF
661 CALL psgemr2d( jw, jw, work(ipt0), 1, 1, desctz0, t, 1+iroffh,
662 $ 1+iroffh, desct, ictxt )
663 CALL psgemr2d( jw, jw, work(ipz0), 1, 1, desctz0, v, 1+iroffh,
664 $ 1+iroffh, descv, ictxt )
665 IF( ictxt_new.GE.0 )
666 $ CALL blacs_gridexit( ictxt_new )
667 IF( myrow+mycol.GT.0 ) THEN
668 DO 40 j = 0, jw-1
669 sr( kwtop+j ) = zero
670 si( kwtop+j ) = zero
671 40 CONTINUE
672 END IF
673 CALL igamn2d( ictxt, 'All', '1-Tree', 1, 1, infqr, 1, -1, -1,
674 $ -1, -1, -1 )
675 CALL sgsum2d( ictxt, 'All', ' ', jw, 1, sr(kwtop), jw, -1, -1 )
676 CALL sgsum2d( ictxt, 'All', ' ', jw, 1, si(kwtop), jw, -1, -1 )
677 END IF
678
679
680
681 IF( infqr.NE.0 )
682 $ infqr = infqr - iroffh
683
684
685
686 DO 50 j = 1, jw - 3
687 CALL pselset( t, j+2, j, desct, zero )
688 CALL pselset( t, j+3, j, desct, zero )
689 50 CONTINUE
690 IF( jw.GT.2 )
691 $
CALL pselset( t, jw, jw-2, desct, zero )
692
693
694
695 resaed = 0.0
696
697
698
699 DO 60 j = 1, nsel
700 iwork( j ) = 0
701 60 CONTINUE
702
703
704
705 mloc = 0
706
707
708
709
710
711 DO 70 j = 1, iroffh + infqr
712 iwork( j ) = 1
713 70 CONTINUE
714
715 ns = jw
716 ilst = infqr + 1 + iroffh
717 IF( ilst.GT.1 ) THEN
718 CALL pselget(
'All',
'1-Tree', elem, t, ilst, ilst-1, desct )
719 bulge = elem.NE.zero
720 IF( bulge ) ilst = ilst+1
721 END IF
722
723 80 CONTINUE
724 IF( ilst.LE.ns+iroffh ) THEN
725
726
727
728 lilst =
max(ilst,ns+iroffh-nb+1)
729 IF( lilst.GT.1 ) THEN
730 CALL pselget(
'All',
'1-Tree', elem, t, lilst, lilst-1,
731 $ desct )
732 bulge = elem.NE.zero
733 IF( bulge ) lilst = lilst+1
734 END IF
735
736
737
738 DO 90 j = iroffh+1, lilst-1
739 iwork( j ) = 1
740 90 CONTINUE
741 lilst0 = lilst
742
743
744
745
746
747 100 CONTINUE
748 IF( lilst.LE.ns+iroffh ) THEN
749 IF( ns.EQ.1 ) THEN
750 bulge = .false.
751 ELSE
752 CALL pselget(
'All',
'1-Tree', elem, t, ns+iroffh,
753 $ ns+iroffh-1, desct )
754 bulge = elem.NE.zero
755 END IF
756
757
758
759 IF( .NOT.bulge ) THEN
760
761
762
763 CALL pselget(
'All',
'1-Tree', elem, t, ns+iroffh,
764 $ ns+iroffh, desct )
765 foo = abs( elem )
766 IF( foo.EQ.zero )
767 $ foo = abs( s )
768 CALL pselget(
'All',
'1-Tree', elem, v, 1+iroffh,
769 $ ns+iroffh, descv )
770 IF( abs( s*elem ).LE.
max( smlnum, ulp*foo ) )
THEN
771
772
773
774 ns = ns - 1
775 ELSE
776
777
778
779 ifst = ns
780 DO 110 j = lilst, jw+iroffh
781 iwork( j ) = 0
782 110 CONTINUE
783 iwork( ifst+iroffh ) = 1
784 CALL pstrord(
'Vectors', iwork, par, jw+iroffh, t, 1,
785 $ 1, desct, v, 1, 1, descv, work,
786 $ work(jw+iroffh+1), mloc,
787 $ work(2*(jw+iroffh)+1), lwork-2*(jw+iroffh),
788 $ iwork(nsel+1), liwork-nsel, info )
789
790
791
792
793 iwork( ifst+iroffh ) = 0
794 iwork( lilst ) = 1
795 lilst = lilst + 1
796
797
798
799
800
801 IF( info.NE.0 ) THEN
802 lilst =
max(info, lilst)
803 ilst =
max(info, ilst)
804 END IF
805 END IF
806 ELSE
807
808
809
810 CALL pselget(
'All',
'1-Tree', elem1, t, ns+iroffh,
811 $ ns+iroffh, desct )
812 CALL pselget(
'All',
'1-Tree', elem2, t, ns+iroffh,
813 $ ns+iroffh-1, desct )
814 CALL pselget(
'All',
'1-Tree', elem3, t, ns+iroffh-1,
815 $ ns+iroffh, desct )
816 foo = abs( elem1 ) + sqrt( abs( elem2 ) )*
817 $ sqrt( abs( elem3 ) )
818 IF( foo.EQ.zero )
819 $ foo = abs( s )
820 CALL pselget(
'All',
'1-Tree', elem1, v, 1+iroffh,
821 $ ns+iroffh, descv )
822 CALL pselget(
'All',
'1-Tree', elem2, v, 1+iroffh,
823 $ ns+iroffh-1, descv )
824 IF(
max( abs( s*elem1 ), abs( s*elem2 ) ).LE.
825 $
max( smlnum, ulp*foo ) )
THEN
826
827
828
829 ns = ns - 2
830 ELSE
831
832
833
834 ifst = ns
835 DO 120 j = lilst, jw+iroffh
836 iwork( j ) = 0
837 120 CONTINUE
838 iwork( ifst+iroffh ) = 1
839 iwork( ifst+iroffh-1 ) = 1
840 CALL pstrord(
'Vectors', iwork, par, jw+iroffh, t, 1,
841 $ 1, desct, v, 1, 1, descv, work,
842 $ work(jw+iroffh+1), mloc,
843 $ work(2*(jw+iroffh)+1), lwork-2*(jw+iroffh),
844 $ iwork(nsel+1), liwork-nsel, info )
845
846
847
848
849 iwork( ifst+iroffh ) = 0
850 iwork( ifst+iroffh-1 ) = 0
851 iwork( lilst ) = 1
852 iwork( lilst+1 ) = 1
853 lilst = lilst + 2
854
855
856
857
858
859 IF( info.NE.0 ) THEN
860 lilst =
max(info, lilst)
861 ilst =
max(info, ilst)
862 END IF
863 END IF
864 END IF
865
866
867
868 GO TO 100
869 END IF
870
871
872
873
874 DO 130 j = ilst, lilst0-1
875 iwork( j ) = 0
876 130 CONTINUE
877 CALL pstrord(
'Vectors', iwork, par, jw+iroffh, t, 1, 1,
878 $ desct, v, 1, 1, descv, work, work(jw+iroffh+1),
879 $ m, work(2*(jw+iroffh)+1), lwork-2*(jw+iroffh),
880 $ iwork(nsel+1), liwork-nsel, info )
881 ilst = m + 1
882
883
884
885
886 IF( info.NE.0 )
887 $ ilst =
max(info, ilst)
888
889
890
891 GO TO 80
892 END IF
893
894
895
896
897 CALL scopy( jw, work(1+iroffh), 1, sr( kwtop ), 1 )
898 CALL scopy( jw, work(jw+2*iroffh+1), 1, si( kwtop ), 1 )
899
900
901
902 resaed = 0.0
903
904
905
906 IF( ns.EQ.0 )
907 $ s = zero
908
909 IF( ns.LT.jw .AND. sortgrad ) THEN
910
911
912
913
914
915 round = 0
916 sorted = .false.
917 i = ns + 1 + iroffh
918 140 CONTINUE
919 IF( sorted )
920 $ GO TO 180
921 sorted = .true.
922 round = round + 1
923
924 kend = i - 1
925 i = infqr + 1 + iroffh
926 IF( i.EQ.ns+iroffh ) THEN
927 k = i + 1
928 ELSE IF( si( kwtop-iroffh + i-1 ).EQ.zero ) THEN
929 k = i + 1
930 ELSE
931 k = i + 2
932 END IF
933 150 CONTINUE
934 IF( k.LE.kend ) THEN
935 IF( k.EQ.i+1 ) THEN
936 evi = abs( sr( kwtop-iroffh+i-1 ) )
937 ELSE
938 evi = abs( sr( kwtop-iroffh+i-1 ) ) +
939 $ abs( si( kwtop-iroffh+i-1 ) )
940 END IF
941
942 IF( k.EQ.kend ) THEN
943 evk = abs( sr( kwtop-iroffh+k-1 ) )
944 ELSEIF( si( kwtop-iroffh+k-1 ).EQ.zero ) THEN
945 evk = abs( sr( kwtop-iroffh+k-1 ) )
946 ELSE
947 evk = abs( sr( kwtop-iroffh+k-1 ) ) +
948 $ abs( si( kwtop-iroffh+k-1 ) )
949 END IF
950
951 IF( evi.GE.evk ) THEN
952 i = k
953 ELSE
954 mloc = 0
955 sorted = .false.
956 ifst = i
957 ilst = k
958 DO 160 j = 1, i-1
959 iwork( j ) = 1
960 mloc = mloc + 1
961 160 CONTINUE
962 IF( k.EQ.i+2 ) THEN
963 iwork( i ) = 0
964 iwork(i+1) = 0
965 ELSE
966 iwork( i ) = 0
967 END IF
968 IF( k.NE.kend .AND. si( kwtop-iroffh+k-1 ).NE.zero ) THEN
969 iwork( k ) = 1
970 iwork(k+1) = 1
971 mloc = mloc + 2
972 ELSE
973 iwork( k ) = 1
974 IF( k.LT.kend ) iwork(k+1) = 0
975 mloc = mloc + 1
976 END IF
977 DO 170 j = k+2, jw+iroffh
978 iwork( j ) = 0
979 170 CONTINUE
980 CALL pstrord(
'Vectors', iwork, par, jw+iroffh, t, 1, 1,
981 $ desct, v, 1, 1, descv, work, work(jw+iroffh+1), m,
982 $ work(2*(jw+iroffh)+1), lwork-2*(jw+iroffh),
983 $ iwork(nsel+1), liwork-nsel, ierr )
984 CALL scopy( jw, work(1+iroffh), 1, sr( kwtop ), 1 )
985 CALL scopy( jw, work(jw+2*iroffh+1), 1, si( kwtop ), 1 )
986 IF( ierr.EQ.0 ) THEN
987 i = ilst
988 ELSE
989 i = k
990 END IF
991 END IF
992 IF( i.EQ.kend ) THEN
993 k = i + 1
994 ELSE IF( si( kwtop-iroffh+i-1 ).EQ.zero ) THEN
995 k = i + 1
996 ELSE
997 k = i + 2
998 END IF
999 GO TO 150
1000 END IF
1001 GO TO 140
1002 180 CONTINUE
1003 END IF
1004
1005
1006
1007 desct( m_ ) = nw+iroffh
1008 desct( n_ ) = nh+iroffh
1009
1010 IF( ns.LT.jw .OR. s.EQ.zero ) THEN
1011 IF( ns.GT.1 .AND. s.NE.zero ) THEN
1012
1013
1014
1015 rrows =
numroc( ns+iroffh, nb, myrow, descv(rsrc_), nprow )
1016 rcols =
numroc( 1, 1, mycol, descv(csrc_), npcol )
1017 CALL descinit( descr, ns+iroffh, 1, nb, 1, descv(rsrc_),
1018 $ descv(csrc_), ictxt,
max(1, rrows), info )
1019 taurows =
numroc( 1, 1, mycol, descv(rsrc_), nprow )
1020 taucols =
numroc( jw+iroffh, nb, mycol, descv(csrc_),
1021 $ npcol )
1022 CALL descinit( desctau, 1, jw+iroffh, 1, nb, descv(rsrc_),
1023 $ descv(csrc_), ictxt,
max(1, taurows), info )
1024
1025 ir = 1
1026 itau = ir + descr( lld_ ) * rcols
1027 ipw = itau + desctau( lld_ ) * taucols
1028
1029 CALL pslaset(
'All', ns+iroffh, 1, zero, zero, work(itau),
1030 $ 1, 1, desctau )
1031
1032 CALL pscopy( ns, v, 1+iroffh, 1+iroffh, descv, descv(m_),
1033 $ work(ir), 1+iroffh, 1, descr, 1 )
1034 CALL pslarfg( ns, beta, 1+iroffh, 1, work(ir), 2+iroffh, 1,
1035 $ descr, 1, work(itau+iroffh) )
1036 CALL pselset( work(ir), 1+iroffh, 1, descr, one )
1037
1038 CALL pslaset(
'Lower', jw-2, jw-2, zero, zero, t, 3+iroffh,
1039 $ 1+iroffh, desct )
1040
1041 CALL pslarf(
'Left', ns, jw, work(ir), 1+iroffh, 1, descr,
1042 $ 1, work(itau+iroffh), t, 1+iroffh, 1+iroffh,
1043 $ desct, work( ipw ) )
1044 CALL pslarf(
'Right', ns, ns, work(ir), 1+iroffh, 1, descr,
1045 $ 1, work(itau+iroffh), t, 1+iroffh, 1+iroffh,
1046 $ desct, work( ipw ) )
1047 CALL pslarf(
'Right', jw, ns, work(ir), 1+iroffh, 1, descr,
1048 $ 1, work(itau+iroffh), v, 1+iroffh, 1+iroffh,
1049 $ descv, work( ipw ) )
1050
1051 itau = 1
1052 ipw = itau + desctau( lld_ ) * taucols
1053 CALL psgehrd( jw+iroffh, 1+iroffh, ns+iroffh, t, 1, 1,
1054 $ desct, work(itau), work( ipw ), lwork-ipw+1, info )
1055 END IF
1056
1057
1058
1059 IF( kwtop.GT.1 ) THEN
1060 CALL pselget(
'All',
'1-Tree', elem, v, 1+iroffh,
1061 $ 1+iroffh, descv )
1062 CALL pselset( h, kwtop, kwtop-1, desch, s*elem )
1063 END IF
1064 CALL pslacpy(
'Upper', jw-1, jw-1, t, 1+iroffh+1, 1+iroffh,
1065 $ desct, h, kwtop+1, kwtop, desch )
1066 CALL pslacpy(
'All', 1, jw, t, 1+iroffh, 1+iroffh, desct, h,
1067 $ kwtop, kwtop, desch )
1068 CALL pslacpy(
'All', jw-1, 1, t, 1+iroffh+1, 1+iroffh+jw-1,
1069 $ desct, h, kwtop+1, kwtop+jw-1, desch )
1070
1071
1072
1073
1074 IF( ns.GT.1 .AND. s.NE.zero ) THEN
1075 CALL psormhr(
'Right',
'No', jw+iroffh, ns+iroffh, 1+iroffh,
1076 $ ns+iroffh, t, 1, 1, desct, work(itau), v, 1,
1077 $ 1, descv, work( ipw ), lwork-ipw+1, info )
1078 END IF
1079
1080
1081
1082 IF( wantt ) THEN
1083 ltop = 1
1084 ELSE
1085 ltop = ktop
1086 END IF
1087 kln =
max( 0, kwtop-ltop )
1088 iroffhh = mod( ltop-1, nb )
1089 icoffhh = mod( kwtop-1, nb )
1090 hhrsrc =
indxg2p( ltop, nb, myrow, desch(rsrc_), nprow )
1091 hhcsrc =
indxg2p( kwtop, nb, mycol, desch(csrc_), npcol )
1092 hhrows =
numroc( kln+iroffhh, nb, myrow, hhrsrc, nprow )
1093 hhcols =
numroc( jw+icoffhh, nb, mycol, hhcsrc, npcol )
1094 CALL descinit( deschh, kln+iroffhh, jw+icoffhh, nb, nb,
1095 $ hhrsrc, hhcsrc, ictxt,
max(1, hhrows), ierr )
1096 CALL psgemm( 'No', 'No', kln, jw, jw, one, h, ltop,
1097 $ kwtop, desch, v, 1+iroffh, 1+iroffh, descv, zero,
1098 $ work, 1+iroffhh, 1+icoffhh, deschh )
1099 CALL pslacpy(
'All', kln, jw, work, 1+iroffhh, 1+icoffhh,
1100 $ deschh, h, ltop, kwtop, desch )
1101
1102
1103
1104 IF( wantt ) THEN
1105 kln = n-kbot
1106 iroffhh = mod( kwtop-1, nb )
1107 icoffhh = mod( kbot, nb )
1108 hhrsrc =
indxg2p( kwtop, nb, myrow, desch(rsrc_), nprow )
1109 hhcsrc =
indxg2p( kbot+1, nb, mycol, desch(csrc_), npcol )
1110 hhrows =
numroc( jw+iroffhh, nb, myrow, hhrsrc, nprow )
1111 hhcols =
numroc( kln+icoffhh, nb, mycol, hhcsrc, npcol )
1112 CALL descinit( deschh, jw+iroffhh, kln+icoffhh, nb, nb,
1113 $ hhrsrc, hhcsrc, ictxt,
max(1, hhrows), ierr )
1114 CALL psgemm( 'Tr', 'No', jw, kln, jw, one, v,
1115 $ 1+iroffh, 1+iroffh, descv, h, kwtop, kbot+1,
1116 $ desch, zero, work, 1+iroffhh, 1+icoffhh, deschh )
1117 CALL pslacpy(
'All', jw, kln, work, 1+iroffhh, 1+icoffhh,
1118 $ deschh, h, kwtop, kbot+1, desch )
1119 END IF
1120
1121
1122
1123 IF( wantz ) THEN
1124 kln = ihiz-iloz+1
1125 iroffzz = mod( iloz-1, nb )
1126 icoffzz = mod( kwtop-1, nb )
1127 zzrsrc =
indxg2p( iloz, nb, myrow, descz(rsrc_), nprow )
1128 zzcsrc =
indxg2p( kwtop, nb, mycol, descz(csrc_), npcol )
1129 zzrows =
numroc( kln+iroffzz, nb, myrow, zzrsrc, nprow )
1130 zzcols =
numroc( jw+icoffzz, nb, mycol, zzcsrc, npcol )
1131 CALL descinit( desczz, kln+iroffzz, jw+icoffzz, nb, nb,
1132 $ zzrsrc, zzcsrc, ictxt,
max(1, zzrows), ierr )
1133 CALL psgemm( 'No', 'No', kln, jw, jw, one, z, iloz,
1134 $ kwtop, descz, v, 1+iroffh, 1+iroffh, descv,
1135 $ zero, work, 1+iroffzz, 1+icoffzz, desczz )
1136 CALL pslacpy(
'All', kln, jw, work, 1+iroffzz, 1+icoffzz,
1137 $ desczz, z, iloz, kwtop, descz )
1138 END IF
1139 END IF
1140
1141
1142
1143
1144
1145
1146 nd = jw - ns
1147 ns = ns - infqr
1148
1149
1150
1151 work( 1 ) = float( lwkopt )
1152 iwork( 1 ) = ilwkopt + nsel
1153
1154
1155
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
integer function iceil(inum, idenom)
integer function indxg2p(indxglob, nb, iproc, isrcproc, nprocs)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
integer function pilaenvx(ictxt, ispec, name, opts, n1, n2, n3, n4)
subroutine pslaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
subroutine pselget(scope, top, alpha, a, ia, ja, desca)
subroutine pselset(a, ia, ja, desca, alpha)
subroutine psgehrd(n, ilo, ihi, a, ia, ja, desca, tau, work, lwork, info)
subroutine pslacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
subroutine pslamve(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb, dwork)
real function pslange(norm, m, n, a, ia, ja, desca, work)
recursive subroutine pslaqr0(wantt, wantz, n, ilo, ihi, h, desch, wr, wi, iloz, ihiz, z, descz, work, lwork, iwork, liwork, info, reclevel)
recursive subroutine pslaqr1(wantt, wantz, n, ilo, ihi, a, desca, wr, wi, iloz, ihiz, z, descz, work, lwork, iwork, ilwork, info)
subroutine pslarf(side, m, n, v, iv, jv, descv, incv, tau, c, ic, jc, descc, work)
subroutine pslarfg(n, alpha, iax, jax, x, ix, jx, descx, incx, tau)
subroutine psormhr(side, trans, m, n, ilo, ihi, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine psrot(n, x, ix, jx, descx, incx, y, iy, jy, descy, incy, cs, sn, work, lwork, info)
subroutine pstrord(compq, select, para, n, t, it, jt, desct, q, iq, jq, descq, wr, wi, m, work, lwork, iwork, liwork, info)