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
227 CHARACTER COLBTOP, ROWBTOP
228 INTEGER IAROW, ICC, ICCOL, ICOFFC, ICROW, ICTXT, IINFO,
229 $ IPW, IROFFA, IROFFC, J, J1, J2, J3, JB, JCC,
230 $ LCM, LCMQ, LWMIN, MI, MPC0, MYCOL, MYROW, NI,
231 $ NPA0, 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 left =
lsame( side,
'L' )
263 notran =
lsame( trans,
'N' )
264
265
266
267 IF( left ) THEN
268 nq = m
269 CALL chk1mat( m, 3, k, 5, ia, ja, desca, 9, info )
270 ELSE
271 nq = n
272 CALL chk1mat( n, 4, k, 5, ia, ja, desca, 9, info )
273 END IF
274 CALL chk1mat( m, 3, n, 4, ic, jc, descc, 14, info )
275 IF( info.EQ.0 ) THEN
276 iroffa = mod( ia-1, desca( mb_ ) )
277 iroffc = mod( ic-1, descc( mb_ ) )
278 icoffc = mod( jc-1, descc( nb_ ) )
279 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
280 $ nprow )
281 icrow =
indxg2p( ic, descc( mb_ ), myrow, descc( rsrc_ ),
282 $ nprow )
283 iccol =
indxg2p( jc, descc( nb_ ), mycol, descc( csrc_ ),
284 $ npcol )
285 mpc0 =
numroc( m+iroffc, descc( mb_ ), myrow, icrow, nprow )
286 nqc0 =
numroc( n+icoffc, descc( nb_ ), mycol, iccol, npcol )
287
288 IF( left ) THEN
289 lwmin =
max( ( desca( nb_ ) * ( desca( nb_ ) - 1 ) ) / 2,
290 $ ( mpc0 + nqc0 ) * desca( nb_ ) ) +
291 $ desca( nb_ ) * desca( nb_ )
292 ELSE
293 npa0 =
numroc( n+iroffa, desca( mb_ ), myrow, iarow,
294 $ nprow )
295 lcm =
ilcm( nprow, npcol )
296 lcmq = lcm / npcol
297 lwmin =
max( ( desca( nb_ ) * ( desca( nb_ ) - 1 ) )
299 $ n+icoffc, desca( nb_ ), 0, 0, npcol ),
300 $ desca( nb_ ), 0, 0, lcmq ), mpc0 ) ) *
301 $ desca( nb_ ) ) + desca( nb_ ) * desca( nb_ )
302 END IF
303
304 work( 1 ) = dcmplx( dble( lwmin ) )
305 lquery = ( lwork.EQ.-1 )
306 IF( .NOT.left .AND. .NOT.
lsame( side,
'R' ) )
THEN
307 info = -1
308 ELSE IF( .NOT.notran .AND. .NOT.
lsame( trans,
'C' ) )
THEN
309 info = -2
310 ELSE IF( k.LT.0 .OR. k.GT.nq ) THEN
311 info = -5
312 ELSE IF( .NOT.left .AND. desca( mb_ ).NE.descc( nb_ ) ) THEN
313 info = -(900+nb_)
314 ELSE IF( left .AND. iroffa.NE.iroffc ) THEN
315 info = -12
316 ELSE IF( left .AND. iarow.NE.icrow ) THEN
317 info = -12
318 ELSE IF( .NOT.left .AND. iroffa.NE.icoffc ) THEN
319 info = -13
320 ELSE IF( left .AND. desca( mb_ ).NE.descc( mb_ ) ) THEN
321 info = -(1400+mb_)
322 ELSE IF( ictxt.NE.descc( ctxt_ ) ) THEN
323 info = -(1400+ctxt_)
324 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
325 info = -16
326 END IF
327 END IF
328
329 IF( left ) THEN
330 idum1( 1 ) = ichar( 'L' )
331 ELSE
332 idum1( 1 ) = ichar( 'R' )
333 END IF
334 idum2( 1 ) = 1
335 IF( notran ) THEN
336 idum1( 2 ) = ichar( 'N' )
337 ELSE
338 idum1( 2 ) = ichar( 'C' )
339 END IF
340 idum2( 2 ) = 2
341 idum1( 3 ) = k
342 idum2( 3 ) = 5
343 IF( lwork.EQ.-1 ) THEN
344 idum1( 4 ) = -1
345 ELSE
346 idum1( 4 ) = 1
347 END IF
348 idum2( 4 ) = 16
349 IF( left ) THEN
350 CALL pchk2mat( m, 3, k, 5, ia, ja, desca, 9, m, 3, n, 4, ic,
351 $ jc, descc, 14, 4, idum1, idum2, info )
352 ELSE
353 CALL pchk2mat( n, 4, k, 5, ia, ja, desca, 9, m, 3, n, 4, ic,
354 $ jc, descc, 14, 4, idum1, idum2, info )
355 END IF
356 END IF
357
358 IF( info.NE.0 ) THEN
359 CALL pxerbla( ictxt,
'PZUNMQR', -info )
360 RETURN
361 ELSE IF( lquery ) THEN
362 RETURN
363 END IF
364
365
366
367 IF( m.EQ.0 .OR. n.EQ.0 .OR. k.EQ.0 )
368 $ RETURN
369
370 CALL pb_topget( ictxt, 'Broadcast', 'Rowwise', rowbtop )
371 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise', colbtop )
372
373 IF( ( left .AND. .NOT.notran ) .OR.
374 $ ( .NOT.left .AND. notran ) ) THEN
375 j1 =
min(
iceil( ja, desca( nb_ ) ) * desca( nb_ ), ja+k-1 )
376 $ + 1
377 j2 = ja+k-1
378 j3 = desca( nb_ )
379 ELSE
380 j1 =
max( ( (ja+k-2) / desca( nb_ ) ) * desca( nb_ ) + 1, ja )
381 j2 =
min(
iceil( ja, desca( nb_ ) ) * desca( nb_ ), ja+k-1 )
382 $ + 1
383 j3 = -desca( nb_ )
384 END IF
385
386 IF( left ) THEN
387 ni = n
388 jcc = jc
389 IF( notran ) THEN
390 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', 'D-ring' )
391 ELSE
392 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', 'I-ring' )
393 END IF
394 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', ' ' )
395 ELSE
396 mi = m
397 icc = ic
398 END IF
399
400
401
402 IF( ( left .AND. .NOT.notran ) .OR. ( .NOT.left .AND. notran ) )
403 $
CALL pzunm2r( side, trans, m, n, j1-ja, a, ia, ja, desca, tau,
404 $ c, ic, jc, descc, work, lwork, iinfo )
405
406 ipw = desca( nb_ ) * desca( nb_ ) + 1
407 DO 10 j = j1, j2, j3
408 jb =
min( desca( nb_ ), k-j+ja )
409
410
411
412
413 CALL pzlarft(
'Forward',
'Columnwise', nq-j+ja, jb, a,
414 $ ia+j-ja, j, desca, tau, work, work( ipw ) )
415 IF( left ) THEN
416
417
418
419 mi = m - j + ja
420 icc = ic + j - ja
421 ELSE
422
423
424
425 ni = n - j + ja
426 jcc = jc + j - ja
427 END IF
428
429
430
431 CALL pzlarfb( side, trans,
'Forward',
'Columnwise', mi, ni,
432 $ jb, a, ia+j-ja, j, desca, work, c, icc, jcc,
433 $ descc, work( ipw ) )
434 10 CONTINUE
435
436
437
438 IF( ( left .AND. notran ) .OR. ( .NOT.left .AND. .NOT.notran ) )
439 $
CALL pzunm2r( side, trans, m, n, j2-ja, a, ia, ja, desca, tau,
440 $ c, ic, jc, descc, work, lwork, iinfo )
441
442 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', rowbtop )
443 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', colbtop )
444
445 work( 1 ) = dcmplx( dble( lwmin ) )
446
447 RETURN
448
449
450
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 pzunm2r(side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)