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