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 REAL 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, ICCOL, ICOFFC, ICROW, ICTXT, IINFO, IPW,
229 $ IROFFA, IROFFC, J, J1, J2, J3, JB, LCM, LCMQ,
230 $ LWMIN, MI, MPC0, MYCOL, MYROW, NI, NPA0, NPCOL,
231 $ NPROW, NQ, NQC0
232
233
234 INTEGER IDUM1( 4 ), IDUM2( 4 )
235
236
239
240
241 LOGICAL LSAME
242 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
244
245
246 INTRINSIC ichar,
max,
min, mod, real
247
248
249
250
251
252 ictxt = desca( ctxt_ )
253 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
254
255
256
257 info = 0
258 IF( nprow.EQ.-1 ) THEN
259 info = -(900+ctxt_)
260 ELSE
261 left =
lsame( side,
'L' )
262 notran =
lsame( trans,
'N' )
263
264
265
266 IF( left ) THEN
267 nq = m
268 CALL chk1mat( m, 3, k, 5, ia, ja, desca, 9, info )
269 ELSE
270 nq = n
271 CALL chk1mat( n, 4, k, 5, ia, ja, desca, 9, info )
272 END IF
273 CALL chk1mat( m, 3, n, 4, ic, jc, descc, 14, info )
274 IF( info.EQ.0 ) THEN
275 iroffa = mod( ia-1, desca( mb_ ) )
276 iroffc = mod( ic-1, descc( mb_ ) )
277 icoffc = mod( jc-1, descc( nb_ ) )
278 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
279 $ nprow )
280 icrow =
indxg2p( ic, descc( mb_ ), myrow, descc( rsrc_ ),
281 $ nprow )
282 iccol =
indxg2p( jc, descc( nb_ ), mycol, descc( csrc_ ),
283 $ npcol )
284 mpc0 =
numroc( m+iroffc, descc( mb_ ), myrow, icrow, nprow )
285 nqc0 =
numroc( n+icoffc, descc( nb_ ), mycol, iccol, npcol )
286
287 IF( left ) THEN
288 lwmin =
max( ( desca( nb_ ) * ( desca( nb_ ) - 1 ) ) / 2,
289 $ ( mpc0 + nqc0 ) * desca( nb_ ) ) +
290 $ desca( nb_ ) * desca( nb_ )
291 ELSE
292 npa0 =
numroc( n+iroffa, desca( mb_ ), myrow, iarow,
293 $ nprow )
294 lcm =
ilcm( nprow, npcol )
295 lcmq = lcm / npcol
296 lwmin =
max( ( desca( nb_ ) * ( desca( nb_ ) - 1 ) )
298 $ n+icoffc, desca( nb_ ), 0, 0, npcol ),
299 $ desca( nb_ ), 0, 0, lcmq ), mpc0 ) ) *
300 $ desca( nb_ ) ) + desca( nb_ ) * desca( nb_ )
301 END IF
302
303 work( 1 ) = real( lwmin )
304 lquery = ( lwork.EQ.-1 )
305 IF( .NOT.left .AND. .NOT.
lsame( side,
'R' ) )
THEN
306 info = -1
307 ELSE IF( .NOT.notran .AND. .NOT.
lsame( trans,
'T' ) )
THEN
308 info = -2
309 ELSE IF( k.LT.0 .OR. k.GT.nq ) THEN
310 info = -5
311 ELSE IF( .NOT.left .AND. desca( mb_ ).NE.descc( nb_ ) ) THEN
312 info = -(900+nb_)
313 ELSE IF( left .AND. iroffa.NE.iroffc ) THEN
314 info = -12
315 ELSE IF( left .AND. iarow.NE.icrow ) THEN
316 info = -12
317 ELSE IF( .NOT.left .AND. iroffa.NE.icoffc ) THEN
318 info = -13
319 ELSE IF( left .AND. desca( mb_ ).NE.descc( mb_ ) ) THEN
320 info = -(1400+mb_)
321 ELSE IF( ictxt.NE.descc( ctxt_ ) ) THEN
322 info = -(1400+ctxt_)
323 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
324 info = -16
325 END IF
326 END IF
327
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( 'T' )
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( m, 3, k, 5, ia, ja, desca, 9, m, 3, n, 4, ic,
350 $ jc, descc, 14, 4, idum1, idum2, info )
351 ELSE
352 CALL pchk2mat( n, 4, k, 5, 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,
'PSORMQL', -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 j1 =
min(
iceil( ja, desca( nb_ ) )*desca( nb_ ), ja+k-1 ) + 1
375 j2 = ja+k-1
376 j3 = desca( nb_ )
377 ELSE
378 j1 =
max( ( (ja+k-2) / desca( nb_ ) ) * desca( nb_ ) + 1, ja )
379 j2 =
min(
iceil( ja, desca( nb_ ) )*desca( nb_ ), ja+k-1 ) + 1
380 j3 = -desca( nb_ )
381 END IF
382
383 IF( left ) THEN
384 ni = n
385 IF( notran ) THEN
386 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', 'I-ring' )
387 ELSE
388 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', 'D-ring' )
389 END IF
390 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', ' ' )
391 ELSE
392 mi = m
393 END IF
394
395
396
397 IF( ( left .AND. notran ) .OR.
398 $ ( .NOT.left .AND. .NOT.notran ) ) THEN
399 jb = j1 - ja
400 IF( left ) THEN
401 mi = m - k + jb
402 ELSE
403 ni = n - k + jb
404 END IF
405 CALL psorm2l( side, trans, mi, ni, jb, a, ia, ja, desca, tau,
406 $ c, ic, jc, descc, work, lwork, iinfo )
407 END IF
408
409 ipw = desca( nb_ ) * desca( nb_ ) + 1
410 DO 10 j = j1, j2, j3
411 jb =
min( desca( nb_ ), k-j+ja )
412
413
414
415
416 CALL pslarft(
'Backward',
'Columnwise', nq-k+j+jb-ja, jb,
417 $ a, ia, j, desca, tau, work, work( ipw ) )
418 IF( left ) THEN
419
420
421
422 mi = m - k + j + jb - ja
423 ELSE
424
425
426
427 ni = n - k + j + jb - ja
428 END IF
429
430
431
432 CALL pslarfb( side, trans,
'Backward',
'Columnwise', mi, ni,
433 $ jb, a, ia, j, desca, work, c, ic, jc, descc,
434 $ work( ipw ) )
435 10 CONTINUE
436
437 IF( ( left .AND. .NOT.notran ) .OR.
438 $ ( .NOT.left .AND. notran ) ) THEN
439 jb = j2 - ja
440 IF( left ) THEN
441 mi = m - k + jb
442 ELSE
443 ni = n - k + jb
444 END IF
445 CALL psorm2l( side, trans, mi, ni, jb, a, ia, ja, desca, tau,
446 $ c, ic, jc, descc, work, lwork, iinfo )
447 END IF
448
449 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', rowbtop )
450 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', colbtop )
451
452 work( 1 ) = real( lwmin )
453
454 RETURN
455
456
457
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 pslarfb(side, trans, direct, storev, m, n, k, v, iv, jv, descv, t, c, ic, jc, descc, work)
subroutine pslarft(direct, storev, n, k, v, iv, jv, descv, tau, t, work)
subroutine psorm2l(side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine pxerbla(ictxt, srname, info)