3
4
5
6
7
8
9
10
11
12
13 CHARACTER*1 ADIST, TRANS
14 INTEGER IACOL, IAROW, ICCOL, ICONTXT, ICROW, LDA, LDC,
15 $ M, N, NB
16 DOUBLE PRECISION BETA
17
18
19 DOUBLE PRECISION A( LDA, * ), C( LDC, * ), WORK( * )
20
21
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 DOUBLE PRECISION ONE, ZERO
181 parameter( one = 1.0d+0, zero = 0.0d+0 )
182
183
184 LOGICAL COLFORM, ROWFORM
185 INTEGER I, IDEX, IGD, INFO, JCCOL, JCROW, JDEX, LCM,
186 $ LCMP, LCMQ, MCCOL, MCROW, ML, MP, MQ, MQ0,
187 $ MRCOL, MRROW, MYCOL, MYROW, NP, NP0, NPCOL,
188 $ NPROW, NQ
189 DOUBLE PRECISION TBETA
190
191
192 LOGICAL LSAME
193 INTEGER ILCM, ICEIL, NUMROC
195
196
197 EXTERNAL blacs_gridinfo, dgebr2d, dgebs2d, dgerv2d,
200
201
203
204
205
206
207
208 IF( m.EQ.0 .OR. n.EQ.0 ) RETURN
209
210 CALL blacs_gridinfo( icontxt, nprow, npcol, myrow, mycol )
211
212 colform =
lsame( adist,
'C' )
213 rowform =
lsame( adist,
'R' )
214
215
216
217 info = 0
218 IF( ( .NOT.colform ) .AND. ( .NOT.rowform ) ) THEN
219 info = 2
220 ELSE IF( m .LT.0 ) THEN
221 info = 4
222 ELSE IF( n .LT.0 ) THEN
223 info = 5
224 ELSE IF( nb.LT.1 ) THEN
225 info = 6
226 ELSE IF( iarow.LT.-1 .OR. iarow.GE.nprow .OR.
227 $ ( iarow.EQ.-1 .AND. colform ) ) THEN
228 info = 12
229 ELSE IF( iacol.LT.-1 .OR. iacol.GE.npcol .OR.
230 $ ( iacol.EQ.-1 .AND. rowform ) ) THEN
231 info = 13
232 ELSE IF( icrow.LT.-1 .OR. icrow.GE.nprow .OR.
233 $ ( icrow.EQ.-1 .AND. rowform ) ) THEN
234 info = 14
235 ELSE IF( iccol.LT.-1 .OR. iccol.GE.npcol .OR.
236 $ ( iccol.EQ.-1 .AND. colform ) ) THEN
237 info = 15
238 END IF
239
240 10 CONTINUE
241 IF( info .NE. 0 ) THEN
242 CALL pxerbla( icontxt,
'PBDTRAN ', info )
243 RETURN
244 END IF
245
246
247
248
249
250 lcm =
ilcm( nprow, npcol )
251 lcmp = lcm / nprow
252 lcmq = lcm / npcol
253 igd = npcol / lcmp
254
255
256
257 IF( colform ) THEN
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 mrrow = mod( nprow+myrow-iarow, nprow )
273 mrcol = mod( npcol+mycol-iccol, npcol )
274 jcrow = icrow
275 IF( icrow.EQ.-1 ) jcrow = iarow
276
277 mp =
numroc( m, nb, myrow, iarow, nprow )
278 mq =
numroc( m, nb, mycol, iccol, npcol )
279 mq0 =
numroc(
numroc(m, nb, 0, 0, npcol), nb, 0, 0, lcmq )
280
281 IF( lda.LT.mp .AND.
282 $ ( iacol.EQ.mycol .OR. iacol.EQ.-1 ) ) THEN
283 info = 8
284 ELSE IF( ldc.LT.n .AND.
285 $ ( icrow.EQ.myrow .OR. icrow.EQ.-1 ) ) THEN
286 info = 11
287 END IF
288 IF( info.NE.0 ) GO TO 10
289
290
291
292 IF( iacol.GE.0 ) THEN
293 tbeta = zero
294 IF( myrow.EQ.jcrow ) tbeta = beta
295
296 DO 20 i = 0,
min( lcm,
iceil(m,nb) ) - 1
297 mcrow = mod( mod(i, nprow) + iarow, nprow )
298 mccol = mod( mod(i, npcol) + iccol, npcol )
299 IF( lcmq.EQ.1 ) mq0 =
numroc( m, nb, i, 0, npcol )
300 jdex = (i/npcol) * nb
301
302
303
304 IF( myrow.EQ.mcrow .AND. mycol.EQ.iacol ) THEN
305
306
307
308 idex = (i/nprow) * nb
309 IF( myrow.EQ.jcrow .AND. mycol.EQ.mccol ) THEN
310 CALL pbdtr2at( icontxt,
'Col', trans, mp-idex, n, nb,
311 $ a(idex+1,1), lda, tbeta, c(1,jdex+1),
312 $ ldc, lcmp, lcmq )
313
314
315
316 ELSE
317 CALL pbdtr2bt( icontxt,
'Col', trans, mp-idex, n, nb,
318 $ a(idex+1,1), lda, zero, work, n,
319 $ lcmp*nb )
320 CALL dgesd2d( icontxt, n, mq0, work, n, jcrow, mccol )
321 END IF
322
323
324
325 ELSE IF( myrow.EQ.jcrow .AND. mycol.EQ.mccol ) THEN
326 IF( lcmq.EQ.1 .AND. tbeta.EQ.zero ) THEN
327 CALL dgerv2d( icontxt, n, mq0, c, ldc, mcrow, iacol )
328 ELSE
329 CALL dgerv2d( icontxt, n, mq0, work, n, mcrow, iacol )
330 CALL pbdtr2af( icontxt,
'Row', n, mq-jdex, nb, work, n,
331 $ tbeta, c(1,jdex+1), ldc, lcmp, lcmq,
332 $ mq0 )
333 END IF
334 END IF
335 20 CONTINUE
336
337
338
339 IF( icrow.EQ.-1 ) THEN
340 IF( myrow.EQ.jcrow ) THEN
341 CALL dgebs2d( icontxt, 'Col', '1-tree', n, mq, c, ldc )
342 ELSE
343 CALL dgebr2d( icontxt, 'Col', '1-tree', n, mq, c, ldc,
344 $ jcrow, mycol )
345 END IF
346 END IF
347
348
349
350 ELSE
351 IF( lcmq.EQ.1 ) mq0 = mq
352
353
354
355
356 DO 30 i = 0, lcmp-1
357 IF( mrcol.EQ.mod( nprow*i+mrrow, npcol ) ) THEN
358 IF( lcmq.EQ.1.AND.(icrow.EQ.-1.OR.icrow.EQ.myrow) ) THEN
359 CALL pbdtr2bt( icontxt,
'Col', trans, mp-i*nb, n, nb,
360 $ a(i*nb+1,1), lda, beta, c, ldc,
361 $ lcmp*nb )
362 ELSE
363 CALL pbdtr2bt( icontxt,
'Col', trans, mp-i*nb, n, nb,
364 $ a(i*nb+1,1), lda, zero, work, n,
365 $ lcmp*nb )
366 END IF
367 END IF
368 30 CONTINUE
369
370
371
372 mcrow = mod( mod(mrcol,nprow)+iarow, nprow )
373 IF( lcmq.GT.1 ) THEN
374 mccol = mod( npcol+mycol-iccol, npcol )
376 $ mcrow, mccol, igd, myrow, mycol, nprow,
377 $ npcol )
378 END IF
379
380
381
382 IF( icrow.EQ.-1 ) THEN
383 IF( myrow.EQ.mcrow ) THEN
384 IF( lcmq.GT.1 )
385 $
CALL pbdtrsrt( icontxt,
'Row', n, mq, nb, work, n, beta,
386 $ c, ldc, lcmp, lcmq, mq0 )
387 CALL dgebs2d( icontxt, 'Col', '1-tree', n, mq, c, ldc )
388 ELSE
389 CALL dgebr2d( icontxt, 'Col', '1-tree', n, mq, c, ldc,
390 $ mcrow, mycol )
391 END IF
392
393
394
395 ELSE
396 IF( lcmq.EQ.1 ) THEN
397 IF( myrow.EQ.mcrow ) THEN
398 IF( myrow.NE.icrow )
399 $ CALL dgesd2d( icontxt, n, mq, work, n, icrow, mycol )
400 ELSE IF( myrow.EQ.icrow ) THEN
401 IF( beta.EQ.zero ) THEN
402 CALL dgerv2d( icontxt, n, mq, c, ldc, mcrow, mycol )
403 ELSE
404 CALL dgerv2d( icontxt, n, mq, work, n, mcrow, mycol )
405 CALL pbdmatadd( icontxt,
'G', n, mq, one, work, n,
406 $ beta, c, ldc )
407 END IF
408 END IF
409
410 ELSE
412 IF( myrow.EQ.mcrow ) THEN
413 IF( myrow.NE.icrow )
414 $ CALL dgesd2d( icontxt, n, ml, work, n, icrow, mycol )
415 ELSE IF( myrow.EQ.icrow ) THEN
416 CALL dgerv2d( icontxt, n, ml, work, n, mcrow, mycol )
417 END IF
418
419 IF( myrow.EQ.icrow )
420 $
CALL pbdtrsrt( icontxt,
'Row', n, mq, nb, work, n, beta,
421 $ c, ldc, lcmp, lcmq, mq0 )
422 END IF
423 END IF
424
425 END IF
426
427
428
429 ELSE
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444 mrrow = mod( nprow+myrow-icrow, nprow )
445 mrcol = mod( npcol+mycol-iacol, npcol )
446 jccol = iccol
447 IF( iccol.EQ.-1 ) jccol = iacol
448
449 np =
numroc( n, nb, myrow, icrow, nprow )
450 nq =
numroc( n, nb, mycol, iacol, npcol )
451 np0 =
numroc(
numroc(n, nb, 0, 0, nprow), nb, 0, 0, lcmp )
452
453 IF( lda.LT.m .AND.
454 $ ( iarow.EQ.myrow .OR. iarow.EQ.-1 ) ) THEN
455 info = 8
456 ELSE IF( ldc.LT.np .AND.
457 $ ( iccol.EQ.mycol .OR. iccol.EQ.-1 ) ) THEN
458 info = 11
459 END IF
460 IF( info.NE.0 ) GO TO 10
461
462
463
464 IF( iarow.GE.0 ) THEN
465 tbeta = zero
466 IF( mycol.EQ.jccol ) tbeta = beta
467
468 DO 40 i = 0,
min( lcm,
iceil(n,nb) ) - 1
469 mcrow = mod( mod(i, nprow) + icrow, nprow )
470 mccol = mod( mod(i, npcol) + iacol, npcol )
471 IF( lcmp.EQ.1 ) np0 =
numroc( n, nb, i, 0, nprow )
472 idex = (i/nprow) * nb
473
474
475
476 IF( myrow.EQ.iarow .AND. mycol.EQ.mccol ) THEN
477
478
479
480 jdex = (i/npcol) * nb
481 IF( myrow.EQ.mcrow .AND. mycol.EQ.jccol ) THEN
482 CALL pbdtr2at( icontxt,
'Row', trans, m, nq-jdex, nb,
483 $ a(1,jdex+1), lda, tbeta, c(idex+1,1),
484 $ ldc, lcmp, lcmq )
485
486
487
488 ELSE
489 CALL pbdtr2bt( icontxt,
'Row', trans, m, nq-jdex, nb,
490 $ a(1,jdex+1), lda, zero, work, np0,
491 $ lcmq*nb )
492 CALL dgesd2d( icontxt, np0, m, work, np0,
493 $ mcrow, jccol )
494 END IF
495
496
497
498 ELSE IF( myrow.EQ.mcrow .AND. mycol.EQ.jccol ) THEN
499 IF( lcmp.EQ.1 .AND. tbeta.EQ.zero ) THEN
500 CALL dgerv2d( icontxt, np0, m, c, ldc, iarow, mccol )
501 ELSE
502 CALL dgerv2d( icontxt, np0, m, work, np0, iarow, mccol )
503 CALL pbdtr2af( icontxt,
'Col', np-idex, m, nb, work,
504 $ np0, tbeta, c(idex+1,1), ldc, lcmp, lcmq,
505 $ np0 )
506 END IF
507 END IF
508 40 CONTINUE
509
510
511
512 IF( iccol.EQ.-1 ) THEN
513 IF( mycol.EQ.jccol ) THEN
514 CALL dgebs2d( icontxt, 'Row', '1-tree', np, m, c, ldc )
515 ELSE
516 CALL dgebr2d( icontxt, 'Row', '1-tree', np, m, c, ldc,
517 $ myrow, jccol )
518 END IF
519 END IF
520
521
522
523 ELSE
524 IF( lcmp.EQ.1 ) np0 = np
525
526
527
528
529 DO 50 i = 0, lcmq-1
530 IF( mrrow.EQ.mod(npcol*i+mrcol, nprow) ) THEN
531 IF( lcmp.EQ.1.AND.(iccol.EQ.-1.OR.iccol.EQ.mycol) ) THEN
532 CALL pbdtr2bt( icontxt,
'Row', trans, m, nq-i*nb, nb,
533 $ a(1,i*nb+1), lda, beta, c, ldc,
534 $ lcmq*nb )
535 ELSE
536 CALL pbdtr2bt( icontxt,
'Row', trans, m, nq-i*nb, nb,
537 $ a(1,i*nb+1), lda, zero, work, np0,
538 $ lcmq*nb )
539 END IF
540 END IF
541 50 CONTINUE
542
543
544
545 mccol = mod( mod(mrrow, npcol)+iacol, npcol )
546 IF( lcmp.GT.1 ) THEN
547 mcrow = mod( nprow+myrow-icrow, nprow )
549 $ np0, mcrow, mccol, igd, myrow, mycol, nprow,
550 $ npcol )
551 END IF
552
553
554
555 IF( iccol.EQ.-1 ) THEN
556 IF( mycol.EQ.mccol ) THEN
557 IF( lcmp.GT.1 )
558 $
CALL pbdtrsrt( icontxt,
'Col', np, m, nb, work, np0,
559 $ beta, c, ldc, lcmp, lcmq, np0 )
560 CALL dgebs2d( icontxt, 'Row', '1-tree', np, m, c, ldc )
561 ELSE
562 CALL dgebr2d( icontxt, 'Row', '1-tree', np, m, c, ldc,
563 $ myrow, mccol )
564 END IF
565
566
567
568 ELSE
569 IF( lcmp.EQ.1 ) THEN
570 IF( mycol.EQ.mccol ) THEN
571 IF( mycol.NE.iccol )
572 $ CALL dgesd2d( icontxt, np, m, work, np, myrow, iccol )
573 ELSE IF( mycol.EQ.iccol ) THEN
574 IF( beta.EQ.zero ) THEN
575 CALL dgerv2d( icontxt, np, m, c, ldc, myrow, mccol )
576 ELSE
577 CALL dgerv2d( icontxt, np, m, work, np, myrow, mccol )
578 CALL pbdmatadd( icontxt,
'G', np, m, one, work, np,
579 $ beta, c, ldc )
580 END IF
581 END IF
582
583 ELSE
584 ml = m *
min( lcmp,
max( 0,
iceil(n,nb) - mcrow ) )
585 IF( mycol.EQ.mccol ) THEN
586 IF( mycol.NE.iccol )
587 $ CALL dgesd2d( icontxt, np0, ml, work, np0,
588 $ myrow, iccol )
589 ELSE IF( mycol.EQ.iccol ) THEN
590 CALL dgerv2d( icontxt, np0, ml, work, np0,
591 $ myrow, mccol )
592 END IF
593
594 IF( mycol.EQ.iccol )
595 $
CALL pbdtrsrt( icontxt,
'Col', np, m, nb, work, np0,
596 $ beta, c, ldc, lcmp, lcmq, np0 )
597 END IF
598 END IF
599
600 END IF
601 END IF
602
603 RETURN
604
605
606
integer function iceil(inum, idenom)
integer function ilcm(m, n)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pbdmatadd(icontxt, mode, m, n, alpha, a, lda, beta, b, ldb)
subroutine pbdtr2bt(icontxt, adist, trans, m, n, nb, a, lda, beta, b, ldb, intv)
subroutine pbdtr2af(icontxt, adist, m, n, nb, a, lda, beta, b, ldb, lcmp, lcmq, nint)
subroutine pbdtr2at(icontxt, adist, trans, m, n, nb, a, lda, beta, b, ldb, lcmp, lcmq)
subroutine pbdtrget(icontxt, adist, m, n, mnb, a, lda, mcrow, mccol, igd, myrow, mycol, nprow, npcol)
subroutine pbdtrsrt(icontxt, adist, m, n, nb, a, lda, beta, b, ldb, lcmp, lcmq, nint)
subroutine pxerbla(ictxt, srname, info)