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