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, TRANST
228 INTEGER I, I1, I2, I3, IACOL, IB, ICC, ICCOL, ICOFFA,
229 $ ICOFFC, ICROW, ICTXT, IINFO, IPW, IROFFC, JCC,
230 $ LCM, LCMP, LWMIN, MI, MPC0, MQA0, MYCOL, MYROW,
231 $ NI, 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( k, 5, m, 3, ia, ja, desca, 9, info )
270 ELSE
271 nq = n
272 CALL chk1mat( k, 5, n, 4, 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 icoffa = mod( ja-1, desca( nb_ ) )
277 iroffc = mod( ic-1, descc( mb_ ) )
278 icoffc = mod( jc-1, descc( nb_ ) )
279 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
280 $ npcol )
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 mqa0 =
numroc( m+icoffa, desca( nb_ ), mycol, iacol,
290 $ npcol )
291 lcm =
ilcm( nprow, npcol )
292 lcmp = lcm / nprow
293 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) )
295 $ m+iroffc, desca( mb_ ), 0, 0, nprow ),
296 $ desca( mb_ ), 0, 0, lcmp ), nqc0 ) ) *
297 $ desca( mb_ ) ) + desca( mb_ ) * desca( mb_ )
298 ELSE
299 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) ) / 2,
300 $ ( mpc0 + nqc0 ) * desca( mb_ ) ) +
301 $ desca( mb_ ) * desca( mb_ )
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( left .AND. desca( nb_ ).NE.descc( mb_ ) ) THEN
313 info = -(900+nb_)
314 ELSE IF( left .AND. icoffa.NE.iroffc ) THEN
315 info = -12
316 ELSE IF( .NOT.left .AND. icoffa.NE.icoffc ) THEN
317 info = -13
318 ELSE IF( .NOT.left .AND. iacol.NE.iccol ) THEN
319 info = -13
320 ELSE IF( .NOT.left .AND. desca( nb_ ).NE.descc( nb_ ) ) THEN
321 info = -(1400+nb_)
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 IF( left ) THEN
329 idum1( 1 ) = ichar( 'L' )
330 ELSE
331 idum1( 1 ) = ichar( 'R' )
332 END IF
333 idum2( 1 ) = 1
334 IF( notran ) THEN
335 idum1( 2 ) = ichar( 'N' )
336 ELSE
337 idum1( 2 ) = ichar( 'C' )
338 END IF
339 idum2( 2 ) = 2
340 idum1( 3 ) = k
341 idum2( 3 ) = 5
342 IF( lwork.EQ.-1 ) THEN
343 idum1( 4 ) = -1
344 ELSE
345 idum1( 4 ) = 1
346 END IF
347 idum2( 4 ) = 16
348 IF( left ) THEN
349 CALL pchk2mat( k, 5, m, 3, ia, ja, desca, 9, m, 3, n, 4, ic,
350 $ jc, descc, 14, 4, idum1, idum2, info )
351 ELSE
352 CALL pchk2mat( k, 5, n, 4, ia, ja, desca, 9, m, 3, n, 4, ic,
353 $ jc, descc, 14, 4, idum1, idum2, info )
354 END IF
355 END IF
356
357 IF( info.NE.0 ) THEN
358 CALL pxerbla( ictxt,
'PZUNMLQ', -info )
359 RETURN
360 ELSE IF( lquery ) THEN
361 RETURN
362 END IF
363
364
365
366 IF( m.EQ.0 .OR. n.EQ.0 .OR. k.EQ.0 )
367 $ RETURN
368
369 CALL pb_topget( ictxt, 'Broadcast', 'Rowwise', rowbtop )
370 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise', colbtop )
371
372 IF( ( left .AND. notran ) .OR.
373 $ ( .NOT.left .AND. .NOT.notran ) ) THEN
374 i1 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
375 $ + 1
376 i2 = ia + k - 1
377 i3 = desca( mb_ )
378 ELSE
379 i1 =
max( ( (ia+k-2) / desca( mb_ ) ) * desca( mb_ ) + 1, ia )
380 i2 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
381 $ + 1
382 i3 = -desca( mb_ )
383 END IF
384
385 IF( left ) THEN
386 ni = n
387 jcc = jc
388 ELSE
389 mi = m
390 icc = ic
391 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', ' ' )
392 IF( notran ) THEN
393 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'D-ring' )
394 ELSE
395 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'I-ring' )
396 END IF
397 END IF
398
399 IF( notran ) THEN
400 transt = 'C'
401 ELSE
402 transt = 'N'
403 END IF
404
405 IF( ( left .AND. notran ) .OR. ( .NOT.left .AND. .NOT.notran ) )
406 $
CALL pzunml2( side, trans, m, n, i1-ia, a, ia, ja, desca, tau,
407 $ c, ic, jc, descc, work, lwork, iinfo )
408
409 ipw = desca( mb_ ) * desca( mb_ ) + 1
410 DO 10 i = i1, i2, i3
411 ib =
min( desca( mb_ ), k-i+ia )
412
413
414
415
416 CALL pzlarft(
'Forward',
'Rowwise', nq-i+ia, ib, a, i, ja+i-ia,
417 $ desca, tau, work, work( ipw ) )
418 IF( left ) THEN
419
420
421
422 mi = m - i + ia
423 icc = ic + i - ia
424 ELSE
425
426
427
428 ni = n - i + ia
429 jcc = jc + i - ia
430 END IF
431
432
433
434 CALL pzlarfb( side, transt,
'Forward',
'Rowwise', mi, ni, ib,
435 $ a, i, ja+i-ia, desca, work, c, icc, jcc, descc,
436 $ work( ipw ) )
437 10 CONTINUE
438
439 IF( ( left .AND. .NOT.notran ) .OR. ( .NOT.left .AND. notran ) )
440 $
CALL pzunml2( side, trans, m, n, i2-ia, a, ia, ja, desca, tau,
441 $ c, ic, jc, descc, work, lwork, iinfo )
442
443 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', rowbtop )
444 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', colbtop )
445
446 work( 1 ) = dcmplx( dble( lwmin ) )
447
448 RETURN
449
450
451
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 pzunml2(side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)