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