4
5
6
7
8
9
10
11
12 IMPLICIT NONE
13
14
15 LOGICAL WANTT, WANTZ
16 INTEGER IHI, IHIZ, ILO, ILOZ, INFO, LDT, LDV, LWORK, N
17
18
19 INTEGER DESCA( * ), DESCZ( * )
20 DOUBLE PRECISION A( * ), T( LDT, * ), V( LDV, * ), WI( * ),
21 $ WORK( * ), WR( * ), Z( * )
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
197 $ LLD_, MB_, M_, NB_, N_, RSRC_
198 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
199 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
200 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
201 DOUBLE PRECISION ZERO, ONE
202 parameter( zero = 0.0d+0, one = 1.0d+0 )
203
204
205 INTEGER CONTXT, HBL, I, I1, I2, IAFIRST, ICOL, ICOL1,
206 $ ICOL2, II, IROW, IROW1, IROW2, ITMP1, ITMP2,
207 $ IERR, J, JAFIRST, JJ, K, L, LDA, LDZ, LLDTMP,
208 $ MYCOL, MYROW, NODE, NPCOL, NPROW, NH, NMIN, NZ,
209 $ HSTEP, VSTEP, KKROW, KKCOL, KLN, LTOP, LEFT,
210 $ RIGHT, UP, DOWN, D1, D2
211
212
213 INTEGER DESCT( 9 ), DESCV( 9 ), DESCWH( 9 ),
214 $ DESCWV( 9 )
215
216
217 INTEGER NUMROC, ILAENV
219
220
221 EXTERNAL blacs_gridinfo,
infog2l, dlaset,
222 $ dlahqr, dlaqr4,
descinit, pdgemm, pdgemr2d,
223 $ dgemm, dlamov, dgesd2d, dgerv2d,
224 $ dgebs2d, dgebr2d, igebs2d, igebr2d
225
226
228
229
230
231 info = 0
232
233 nh = ihi - ilo + 1
234 nz = ihiz - iloz + 1
235 IF( n.EQ.0 .OR. nh.EQ.0 )
236 $ RETURN
237
238
239
240 hbl = desca( mb_ )
241 contxt = desca( ctxt_ )
242 lda = desca( lld_ )
243 iafirst = desca( rsrc_ )
244 jafirst = desca( csrc_ )
245 ldz = descz( lld_ )
246 CALL blacs_gridinfo( contxt, nprow, npcol, myrow, mycol )
247 node = myrow*npcol + mycol
248 left = mod( mycol+npcol-1, npcol )
249 right = mod( mycol+1, npcol )
250 up = mod( myrow+nprow-1, nprow )
251 down = mod( myrow+1, nprow )
252
253
254
255
256 i = ihi
257 l = ilo
258 IF( wantt ) THEN
259 i1 = 1
260 i2 = n
261 ltop = 1
262 ELSE
263 i1 = l
264 i2 = i
265 ltop = l
266 END IF
267
268
269
270 CALL infog2l( ilo, ilo, desca, nprow, npcol, myrow, mycol,
271 $ irow, icol, ii, jj )
272 IF ( myrow .EQ. ii ) THEN
273 CALL descinit( desct, nh, nh, nh, nh, ii, jj, contxt,
274 $ ldt, ierr )
275 CALL descinit( descv, nh, nh, nh, nh, ii, jj, contxt,
276 $ ldv, ierr )
277 ELSE
278 CALL descinit( desct, nh, nh, nh, nh, ii, jj, contxt,
279 $ 1, ierr )
280 CALL descinit( descv, nh, nh, nh, nh, ii, jj, contxt,
281 $ 1, ierr )
282 END IF
283 CALL pdgemr2d( nh, nh, a, ilo, ilo, desca, t, 1, 1, desct,
284 $ contxt )
285 IF ( myrow .EQ. ii .AND. mycol .EQ. jj ) THEN
286 CALL dlaset( 'All', nh, nh, zero, one, v, ldv )
287 nmin = ilaenv( 12, 'DLAQR3', 'SV', nh, 1, nh, lwork )
288 IF( nh .GT. nmin ) THEN
289 CALL dlaqr4( .true., .true., nh, 1, nh, t, ldt, wr( ilo ),
290 $ wi( ilo ), 1, nh, v, ldv, work, lwork, info )
291
292 CALL dlaset( 'L', nh-2, nh-2, zero, zero, t( 3, 1 ), ldt )
293 ELSE
294 CALL dlahqr( .true., .true., nh, 1, nh, t, ldt, wr( ilo ),
295 $ wi( ilo ), 1, nh, v, ldv, info )
296 END IF
297 CALL dgebs2d( contxt, 'All', ' ', nh, nh, v, ldv )
298 CALL igebs2d( contxt, 'All', ' ', 1, 1, info, 1 )
299 ELSE
300 CALL dgebr2d( contxt, 'All', ' ', nh, nh, v, ldv, ii, jj )
301 CALL igebr2d( contxt, 'All', ' ', 1, 1, info, 1, ii, jj )
302 END IF
303 IF( info .NE. 0 ) info = info+ilo-1
304
305
306
307 CALL pdgemr2d( nh, nh, t, 1, 1, desct, a, ilo, ilo, desca,
308 $ contxt )
309
310
311
312 IF( mod( ilo-1, hbl )+nh .LE. hbl ) THEN
313
314
315
316
317 hstep = lwork / nh
318 vstep = hstep
319
320 IF( wantt ) THEN
321
322
323
324 CALL infog2l( ilo, i+1, desca, nprow, npcol, myrow,
325 $ mycol, irow, icol, ii, jj )
326 IF( myrow .EQ. ii ) THEN
327 icol1 =
numroc( n, hbl, mycol, jafirst, npcol )
328 DO 10 kkcol = icol, icol1, hstep
329 kln =
min( hstep, icol1-kkcol+1 )
330 CALL dgemm( 'T', 'N', nh, kln, nh, one, v,
331 $ ldv, a( irow+(kkcol-1)*lda ), lda, zero, work,
332 $ nh )
333 CALL dlamov( 'A', nh, kln, work, nh,
334 $ a( irow+(kkcol-1)*lda ), lda )
335 10 CONTINUE
336 END IF
337
338
339
340 CALL infog2l( ltop, ilo, desca, nprow, npcol, myrow,
341 $ mycol, irow, icol, ii, jj )
342 IF( mycol .EQ. jj ) THEN
343 CALL infog2l( ilo-1, ilo, desca, nprow, npcol,
344 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
345 IF( myrow .NE. itmp1 ) irow1 = irow1-1
346 DO 20 kkrow = irow, irow1, vstep
347 kln =
min( vstep, irow1-kkrow+1 )
348 CALL dgemm( 'N', 'N', kln, nh, nh, one,
349 $ a( kkrow+(icol-1)*lda ), lda, v, ldv, zero,
350 $ work, kln )
351 CALL dlamov( 'A', kln, nh, work, kln,
352 $ a( kkrow+(icol-1)*lda ), lda )
353 20 CONTINUE
354 END IF
355 END IF
356
357
358
359 IF( wantz ) THEN
360 CALL infog2l( iloz, ilo, descz, nprow, npcol, myrow,
361 $ mycol, irow, icol, ii, jj )
362 IF( mycol .EQ. jj ) THEN
363 CALL infog2l( ihiz, ilo, descz, nprow, npcol,
364 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
365 IF( myrow .NE. itmp1 ) irow1 = irow1-1
366 DO 30 kkrow = irow, irow1, vstep
367 kln =
min( vstep, irow1-kkrow+1 )
368 CALL dgemm( 'N', 'N', kln, nh, nh, one,
369 $ z( kkrow+(icol-1)*ldz ), ldz, v, ldv, zero,
370 $ work, kln )
371 CALL dlamov( 'A', kln, nh, work, kln,
372 $ z( kkrow+(icol-1)*ldz ), ldz )
373 30 CONTINUE
374 END IF
375 END IF
376
377 ELSE IF( mod( ilo-1, hbl )+nh .LE. 2*hbl ) THEN
378
379
380
381
382
383 d1 = hbl - mod( ilo-1, hbl )
384 d2 = nh - d1
385 hstep = lwork / nh
386 vstep = hstep
387
388 IF( wantt ) THEN
389
390
391
392 CALL infog2l( ilo, i+1, desca, nprow, npcol, myrow,
393 $ mycol, irow, icol, ii, jj )
394 IF( myrow .EQ. up ) THEN
395 IF( myrow .EQ. ii ) THEN
396 icol1 =
numroc( n, hbl, mycol, jafirst, npcol )
397 DO 40 kkcol = icol, icol1, hstep
398 kln =
min( hstep, icol1-kkcol+1 )
399 CALL dgemm( 'T', 'N', nh, kln, nh, one, v,
400 $ nh, a( irow+(kkcol-1)*lda ), lda, zero,
401 $ work, nh )
402 CALL dlamov( 'A', nh, kln, work, nh,
403 $ a( irow+(kkcol-1)*lda ), lda )
404 40 CONTINUE
405 END IF
406 ELSE
407 IF( myrow .EQ. ii ) THEN
408 icol1 =
numroc( n, hbl, mycol, jafirst, npcol )
409 DO 50 kkcol = icol, icol1, hstep
410 kln =
min( hstep, icol1-kkcol+1 )
411 CALL dgemm( 'T', 'N', d2, kln, d1, one,
412 $ v( 1, d1+1 ), ldv, a( irow+(kkcol-1)*lda ),
413 $ lda, zero, work( d1+1 ), nh )
414 CALL dgesd2d( contxt, d2, kln, work( d1+1 ),
415 $ nh, down, mycol )
416 CALL dgerv2d( contxt, d1, kln, work, nh, down,
417 $ mycol )
418 CALL dgemm( 'T', 'N', d1, kln, d1, one,
419 $ v, ldv, a( irow+(kkcol-1)*lda ), lda, one,
420 $ work, nh )
421 CALL dlamov( 'A', d1, kln, work, nh,
422 $ a( irow+(kkcol-1)*lda ), lda )
423 50 CONTINUE
424 ELSE IF( up .EQ. ii ) THEN
425 icol1 =
numroc( n, hbl, mycol, jafirst, npcol )
426 DO 60 kkcol = icol, icol1, hstep
427 kln =
min( hstep, icol1-kkcol+1 )
428 CALL dgemm( 'T', 'N', d1, kln, d2, one,
429 $ v( d1+1, 1 ), ldv, a( irow+(kkcol-1)*lda ),
430 $ lda, zero, work, nh )
431 CALL dgesd2d( contxt, d1, kln, work, nh, up,
432 $ mycol )
433 CALL dgerv2d( contxt, d2, kln, work( d1+1 ),
434 $ nh, up, mycol )
435 CALL dgemm( 'T', 'N', d2, kln, d2, one,
436 $ v( d1+1, d1+1 ), ldv,
437 $ a( irow+(kkcol-1)*lda ), lda, one,
438 $ work( d1+1 ), nh )
439 CALL dlamov( 'A', d2, kln, work( d1+1 ), nh,
440 $ a( irow+(kkcol-1)*lda ), lda )
441 60 CONTINUE
442 END IF
443 END IF
444
445
446
447 CALL infog2l( ltop, ilo, desca, nprow, npcol, myrow,
448 $ mycol, irow, icol, ii, jj )
449 IF( mycol .EQ. left ) THEN
450 IF( mycol .EQ. jj ) THEN
451 CALL infog2l( ilo-1, ilo, desca, nprow, npcol,
452 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
453 IF( myrow .NE. itmp1 ) irow1 = irow1-1
454 DO 70 kkrow = irow, irow1, vstep
455 kln =
min( vstep, irow1-kkrow+1 )
456 CALL dgemm( 'N', 'N', kln, nh, nh, one,
457 $ a( kkrow+(icol-1)*lda ), lda, v, ldv,
458 $ zero, work, kln )
459 CALL dlamov( 'A', kln, nh, work, kln,
460 $ a( kkrow+(icol-1)*lda ), lda )
461 70 CONTINUE
462 END IF
463 ELSE
464 IF( mycol .EQ. jj ) THEN
465 CALL infog2l( ilo-1, ilo, desca, nprow, npcol,
466 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
467 IF( myrow .NE. itmp1 ) irow1 = irow1-1
468 DO 80 kkrow = irow, irow1, vstep
469 kln =
min( vstep, irow1-kkrow+1 )
470 CALL dgemm( 'N', 'N', kln, d2, d1, one,
471 $ a( kkrow+(icol-1)*lda ), lda, v( 1, d1+1 ),
472 $ ldv, zero, work( 1+d1*kln ), kln )
473 CALL dgesd2d( contxt, kln, d2, work( 1+d1*kln ),
474 $ kln, myrow, right )
475 CALL dgerv2d( contxt, kln, d1, work, kln, myrow,
476 $ right )
477 CALL dgemm( 'N', 'N', kln, d1, d1, one,
478 $ a( kkrow+(icol-1)*lda ), lda, v, ldv, one,
479 $ work, kln )
480 CALL dlamov( 'A', kln, d1, work, kln,
481 $ a( kkrow+(icol-1)*lda ), lda )
482 80 CONTINUE
483 ELSE IF ( left .EQ. jj ) THEN
484 CALL infog2l( ilo-1, ilo, desca, nprow, npcol,
485 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
486 IF( myrow .NE. itmp1 ) irow1 = irow1-1
487 DO 90 kkrow = irow, irow1, vstep
488 kln =
min( vstep, irow1-kkrow+1 )
489 CALL dgemm( 'N', 'N', kln, d1, d2, one,
490 $ a( kkrow+(icol-1)*lda ), lda, v( d1+1, 1 ),
491 $ ldv, zero, work, kln )
492 CALL dgesd2d( contxt, kln, d1, work, kln, myrow,
493 $ left )
494 CALL dgerv2d( contxt, kln, d2, work( 1+d1*kln ),
495 $ kln, myrow, left )
496 CALL dgemm( 'N', 'N', kln, d2, d2, one,
497 $ a( kkrow+(icol-1)*lda ), lda, v( d1+1, d1+1 ),
498 $ ldv, one, work( 1+d1*kln ), kln )
499 CALL dlamov( 'A', kln, d2, work( 1+d1*kln ), kln,
500 $ a( kkrow+(icol-1)*lda ), lda )
501 90 CONTINUE
502 END IF
503 END IF
504 END IF
505
506
507
508 IF( wantz ) THEN
509 CALL infog2l( iloz, ilo, descz, nprow, npcol, myrow,
510 $ mycol, irow, icol, ii, jj )
511 IF( mycol .EQ. left ) THEN
512 IF( mycol .EQ. jj ) THEN
513 CALL infog2l( ihiz, ilo, descz, nprow, npcol,
514 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
515 IF( myrow .NE. itmp1 ) irow1 = irow1-1
516 DO 100 kkrow = irow, irow1, vstep
517 kln =
min( vstep, irow1-kkrow+1 )
518 CALL dgemm( 'N', 'N', kln, nh, nh, one,
519 $ z( kkrow+(icol-1)*ldz ), ldz, v, ldv, zero,
520 $ work, kln )
521 CALL dlamov( 'A', kln, nh, work, kln,
522 $ z( kkrow+(icol-1)*ldz ), ldz )
523 100 CONTINUE
524 END IF
525 ELSE
526 IF( mycol .EQ. jj ) THEN
527 CALL infog2l( ihiz, ilo, descz, nprow, npcol,
528 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
529 IF( myrow .NE. itmp1 ) irow1 = irow1-1
530 DO 110 kkrow = irow, irow1, vstep
531 kln =
min( vstep, irow1-kkrow+1 )
532 CALL dgemm( 'N', 'N', kln, d2, d1, one,
533 $ z( kkrow+(icol-1)*ldz ), ldz, v( 1, d1+1 ),
534 $ ldv, zero, work( 1+d1*kln ), kln )
535 CALL dgesd2d( contxt, kln, d2, work( 1+d1*kln ),
536 $ kln, myrow, right )
537 CALL dgerv2d( contxt, kln, d1, work, kln, myrow,
538 $ right )
539 CALL dgemm( 'N', 'N', kln, d1, d1, one,
540 $ z( kkrow+(icol-1)*ldz ), ldz, v, ldv, one,
541 $ work, kln )
542 CALL dlamov( 'A', kln, d1, work, kln,
543 $ z( kkrow+(icol-1)*ldz ), ldz )
544 110 CONTINUE
545 ELSE IF( left .EQ. jj ) THEN
546 CALL infog2l( ihiz, ilo, descz, nprow, npcol,
547 $ myrow, mycol, irow1, icol1, itmp1, itmp2 )
548 IF( myrow .NE. itmp1 ) irow1 = irow1-1
549 DO 120 kkrow = irow, irow1, vstep
550 kln =
min( vstep, irow1-kkrow+1 )
551 CALL dgemm( 'N', 'N', kln, d1, d2, one,
552 $ z( kkrow+(icol-1)*ldz ), ldz, v( d1+1, 1 ),
553 $ ldv, zero, work, kln )
554 CALL dgesd2d( contxt, kln, d1, work, kln, myrow,
555 $ left )
556 CALL dgerv2d( contxt, kln, d2, work( 1+d1*kln ),
557 $ kln, myrow, left )
558 CALL dgemm( 'N', 'N', kln, d2, d2, one,
559 $ z( kkrow+(icol-1)*ldz ), ldz,
560 $ v( d1+1, d1+1 ), ldv, one, work( 1+d1*kln ),
561 $ kln )
562 CALL dlamov( 'A', kln, d2, work( 1+d1*kln ),
563 $ kln, z( kkrow+(icol-1)*ldz ), ldz )
564 120 CONTINUE
565 END IF
566 END IF
567 END IF
568
569 ELSE
570
571
572
573
574
575 hstep = lwork / nh * npcol
576 vstep = lwork / nh * nprow
577 lldtmp =
numroc( nh, nh, myrow, 0, nprow )
578 lldtmp =
max( 1, lldtmp )
579 CALL descinit( descv, nh, nh, nh, nh, 0, 0, contxt,
580 $ lldtmp, ierr )
581 CALL descinit( descwh, nh, hstep, nh, lwork / nh, 0, 0,
582 $ contxt, lldtmp, ierr )
583
584 IF( wantt ) THEN
585
586
587
588 DO 130 kkcol = i+1, n, hstep
589 kln =
min( hstep, n-kkcol+1 )
590 CALL pdgemm( 'T', 'N', nh, kln, nh, one, v, 1, 1,
591 $ descv, a, ilo, kkcol, desca, zero, work, 1, 1,
592 $ descwh )
593 CALL pdgemr2d( nh, kln, work, 1, 1, descwh, a,
594 $ ilo, kkcol, desca, contxt )
595 130 CONTINUE
596
597
598
599 DO 140 kkrow = ltop, ilo-1, vstep
600 kln =
min( vstep, ilo-kkrow )
601 lldtmp =
numroc( kln, lwork / nh, myrow, 0, nprow )
602 lldtmp =
max( 1, lldtmp )
603 CALL descinit( descwv, kln, nh, lwork / nh, nh, 0, 0,
604 $ contxt, lldtmp, ierr )
605 CALL pdgemm( 'N', 'N', kln, nh, nh, one, a, kkrow,
606 $ ilo, desca, v, 1, 1, descv, zero, work, 1, 1,
607 $ descwv )
608 CALL pdgemr2d( kln, nh, work, 1, 1, descwv, a, kkrow,
609 $ ilo, desca, contxt )
610 140 CONTINUE
611 END IF
612
613
614
615 IF( wantz ) THEN
616 DO 150 kkrow = iloz, ihiz, vstep
617 kln =
min( vstep, ihiz-kkrow+1 )
618 lldtmp =
numroc( kln, lwork / nh, myrow, 0, nprow )
619 lldtmp =
max( 1, lldtmp )
620 CALL descinit( descwv, kln, nh, lwork / nh, nh, 0, 0,
621 $ contxt, lldtmp, ierr )
622 CALL pdgemm( 'N', 'N', kln, nh, nh, one, z, kkrow,
623 $ ilo, descz, v, 1, 1, descv, zero, work, 1, 1,
624 $ descwv )
625 CALL pdgemr2d( kln, nh, work, 1, 1, descwv, z,
626 $ kkrow, ilo, descz, contxt )
627 150 CONTINUE
628 END IF
629 END IF
630
631
632
subroutine descinit(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld, info)
subroutine infog2l(grindx, gcindx, desc, nprow, npcol, myrow, mycol, lrindx, lcindx, rsrc, csrc)
integer function numroc(n, nb, iproc, isrcproc, nprocs)