3
4
5
6
7
8
9
10 CHARACTER SIDE, TRANS
11 INTEGER IA, IC, INFO, JA, JC, K, L, LWORK, M, N
12
13
14 INTEGER DESCA( * ), DESCC( * )
15 COMPLEX*16 A( * ), C( * ), TAU( * ), WORK( * )
16
17
18
19
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
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
225 $ LLD_, MB_, M_, NB_, N_, RSRC_
226 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
227 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
228 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
229
230
231 LOGICAL LEFT, LQUERY, NOTRAN
232 CHARACTER COLBTOP, ROWBTOP, TRANST
233 INTEGER I, I1, I2, I3, IACOL, IB, ICC, ICCOL, ICOFFA,
234 $ ICOFFC, ICROW, ICTXT, IINFO, IPW, IROFFC, JAA,
235 $ JCC, LCM, LCMP, LWMIN, MI, MPC0, MQA0, MYCOL,
236 $ MYROW, NI, NPCOL, NPROW, NQ, NQC0
237
238
239 INTEGER IDUM1( 5 ), IDUM2( 5 )
240
241
245
246
247 LOGICAL LSAME
248 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
250
251
252 INTRINSIC dble, dcmplx, ichar,
max,
min, mod
253
254
255
256
257
258 ictxt = desca( ctxt_ )
259 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
260
261
262
263 info = 0
264 IF( nprow.EQ.-1 ) THEN
265 info = -(900+ctxt_)
266 ELSE
267 left =
lsame( side,
'L' )
268 notran =
lsame( trans,
'N' )
269
270
271
272 IF( left ) THEN
273 nq = m
274 CALL chk1mat( k, 5, m, 3, ia, ja, desca, 10, info )
275 ELSE
276 nq = n
277 CALL chk1mat( k, 5, n, 4, ia, ja, desca, 10, info )
278 END IF
279 CALL chk1mat( m, 3, n, 4, ic, jc, descc, 15, info )
280 IF( info.EQ.0 ) THEN
281 icoffa = mod( ja-1, desca( nb_ ) )
282 iroffc = mod( ic-1, descc( mb_ ) )
283 icoffc = mod( jc-1, descc( nb_ ) )
284 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
285 $ npcol )
286 icrow =
indxg2p( ic, descc( mb_ ), myrow, descc( rsrc_ ),
287 $ nprow )
288 iccol =
indxg2p( jc, descc( nb_ ), mycol, descc( csrc_ ),
289 $ npcol )
290 mpc0 =
numroc( m+iroffc, descc( mb_ ), myrow, icrow, nprow )
291 nqc0 =
numroc( n+icoffc, descc( nb_ ), mycol, iccol, npcol )
292
293 IF( left ) THEN
294 mqa0 =
numroc( m+icoffa, desca( nb_ ), mycol, iacol,
295 $ npcol )
296 lcm =
ilcm( nprow, npcol )
297 lcmp = lcm / nprow
298 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) )
300 $ m+iroffc, desca( mb_ ), 0, 0, nprow ),
301 $ desca( mb_ ), 0, 0, lcmp ), nqc0 ) ) *
302 $ desca( mb_ ) ) + desca( mb_ ) * desca( mb_ )
303 ELSE
304 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) ) / 2,
305 $ ( mpc0 + nqc0 ) * desca( mb_ ) ) +
306 $ desca( mb_ ) * desca( mb_ )
307 END IF
308
309 work( 1 ) = dcmplx( dble( lwmin ) )
310 lquery = ( lwork.EQ.-1 )
311 IF( .NOT.left .AND. .NOT.
lsame( side,
'R' ) )
THEN
312 info = -1
313 ELSE IF( .NOT.notran .AND. .NOT.
lsame( trans,
'C' ) )
THEN
314 info = -2
315 ELSE IF( k.LT.0 .OR. k.GT.nq ) THEN
316 info = -5
317 ELSE IF( k.LT.0 .OR. k.GT.nq ) THEN
318 info = -6
319 ELSE IF( left .AND. desca( nb_ ).NE.descc( mb_ ) ) THEN
320 info = -(1000+nb_)
321 ELSE IF( left .AND. icoffa.NE.iroffc ) THEN
322 info = -13
323 ELSE IF( .NOT.left .AND. icoffa.NE.icoffc ) THEN
324 info = -14
325 ELSE IF( .NOT.left .AND. iacol.NE.iccol ) THEN
326 info = -14
327 ELSE IF( .NOT.left .AND. desca( nb_ ).NE.descc( nb_ ) ) THEN
328 info = -(1500+nb_)
329 ELSE IF( ictxt.NE.descc( ctxt_ ) ) THEN
330 info = -(1500+ctxt_)
331 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
332 info = -17
333 END IF
334 END IF
335 IF( left ) THEN
336 idum1( 1 ) = ichar( 'L' )
337 ELSE
338 idum1( 1 ) = ichar( 'R' )
339 END IF
340 idum2( 1 ) = 1
341 IF( notran ) THEN
342 idum1( 2 ) = ichar( 'N' )
343 ELSE
344 idum1( 2 ) = ichar( 'C' )
345 END IF
346 idum2( 2 ) = 2
347 idum1( 3 ) = k
348 idum2( 3 ) = 5
349 idum1( 4 ) = l
350 idum2( 4 ) = 6
351 IF( lwork.EQ.-1 ) THEN
352 idum1( 5 ) = -1
353 ELSE
354 idum1( 5 ) = 1
355 END IF
356 idum2( 5 ) = 17
357 IF( left ) THEN
358 CALL pchk2mat( k, 5, m, 3, ia, ja, desca, 10, m, 3, n, 4,
359 $ ic, jc, descc, 15, 5, idum1, idum2, info )
360 ELSE
361 CALL pchk2mat( k, 5, n, 4, ia, ja, desca, 10, m, 3, n, 4,
362 $ ic, jc, descc, 15, 5, idum1, idum2, info )
363 END IF
364 END IF
365
366 IF( info.NE.0 ) THEN
367 CALL pxerbla( ictxt,
'PZUNMRZ', -info )
368 RETURN
369 ELSE IF( lquery ) THEN
370 RETURN
371 END IF
372
373
374
375 IF( m.EQ.0 .OR. n.EQ.0 .OR. k.EQ.0 )
376 $ RETURN
377
378 CALL pb_topget( ictxt, 'Broadcast', 'Rowwise', rowbtop )
379 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise', colbtop )
380
381 IF( ( left .AND. .NOT.notran ) .OR.
382 $ ( .NOT.left .AND. notran ) ) THEN
383 i1 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
384 $ + 1
385 i2 = ia + k - 1
386 i3 = desca( mb_ )
387 ELSE
388 i1 =
max( ( (ia+k-2) / desca( mb_ ) ) * desca( mb_ ) + 1, ia )
389 i2 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
390 $ + 1
391 i3 = -desca( mb_ )
392 END IF
393
394 IF( left ) THEN
395 ni = n
396 jcc = jc
397 jaa = ja + m - l
398 ELSE
399 mi = m
400 icc = ic
401 jaa = ja + n - l
402 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', ' ' )
403 IF( notran ) THEN
404 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'I-ring' )
405 ELSE
406 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'D-ring' )
407 END IF
408 END IF
409
410 IF( notran ) THEN
411 transt = 'C'
412 ELSE
413 transt = 'N'
414 END IF
415
416 IF( ( left .AND. .NOT.notran ) .OR.
417 $ ( .NOT.left .AND. notran ) ) THEN
418 ib = i1 - ia
419 IF( left ) THEN
420 mi = m
421 ELSE
422 ni = n
423 END IF
424 CALL pzunmr3( side, trans, mi, ni, ib, l, a, ia, ja, desca,
425 $ tau, c, ic, jc, descc, work, lwork, iinfo )
426 END IF
427
428 ipw = desca( mb_ )*desca( mb_ ) + 1
429 DO 10 i = i1, i2, i3
430 ib =
min( desca( mb_ ), k-i+ia )
431
432
433
434
435 CALL pzlarzt(
'Backward',
'Rowwise', l, ib, a, i, jaa, desca,
436 $ tau, work, work( ipw ) )
437 IF( left ) THEN
438
439
440
441 mi = m - i + ia
442 icc = ic + i - ia
443 ELSE
444
445
446
447 ni = n - i + ia
448 jcc = jc + i - ia
449 END IF
450
451
452
453 CALL pzlarzb( side, transt,
'Backward',
'Rowwise', mi, ni, ib,
454 $ l, a, i, jaa, desca, work, c, icc, jcc, descc,
455 $ work( ipw ) )
456 10 CONTINUE
457
458 IF( ( left .AND. .NOT.notran ) .OR.
459 $ ( .NOT.left .AND. notran ) ) THEN
460 ib = i2 - ia
461 IF( left ) THEN
462 mi = m
463 ELSE
464 ni = n
465 END IF
466 CALL pzunmr3( side, trans, mi, ni, ib, l, a, ia, ja, desca,
467 $ tau, c, ic, jc, descc, work, lwork, iinfo )
468 END IF
469
470 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', rowbtop )
471 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', colbtop )
472
473 work( 1 ) = dcmplx( dble( lwmin ) )
474
475 RETURN
476
477
478
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
integer function iceil(inum, idenom)
integer function ilcm(m, n)
integer function indxg2p(indxglob, nb, iproc, isrcproc, nprocs)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pchk2mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, mb, mbpos0, nb, nbpos0, ib, jb, descb, descbpos0, nextra, ex, expos, info)
subroutine pxerbla(ictxt, srname, info)
subroutine pzlarzb(side, trans, direct, storev, m, n, k, l, v, iv, jv, descv, t, c, ic, jc, descc, work)
subroutine pzlarzt(direct, storev, n, k, v, iv, jv, descv, tau, t, work)
subroutine pzunmr3(side, trans, m, n, k, l, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)