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, 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
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 IF(
lsame( side,
'L' ) )
THEN
262 left = .true.
263 right = .false.
264 ELSE
265 left = .false.
266 right = .true.
267 END IF
268 IF(
lsame( trans,
'N' ) )
THEN
269 notran = .true.
270 tran = .false.
271 ELSE
272 notran = .false.
273 tran = .true.
274 END IF
275
276
277
278 IF( left ) THEN
279 nq = m
280 CALL chk1mat( k, 5, m, 3, ia, ja, desca, 9, info )
281 ELSE
282 nq = n
283 CALL chk1mat( k, 5, n, 4, ia, ja, desca, 9, info )
284 END IF
285 CALL chk1mat( m, 3, n, 4, ic, jc, descc, 14, info )
286 IF( info.EQ.0 ) THEN
287 icoffa = mod( ja-1, desca( nb_ ) )
288 iroffc = mod( ic-1, descc( mb_ ) )
289 icoffc = mod( jc-1, descc( nb_ ) )
290 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
291 $ npcol )
292 icrow =
indxg2p( ic, descc( mb_ ), myrow, descc( rsrc_ ),
293 $ nprow )
294 iccol =
indxg2p( jc, descc( nb_ ), mycol, descc( csrc_ ),
295 $ npcol )
296 mpc0 =
numroc( m+iroffc, descc( mb_ ), myrow, icrow, nprow )
297 nqc0 =
numroc( n+icoffc, descc( nb_ ), mycol, iccol, npcol )
298
299 IF( left ) THEN
300 mqa0 =
numroc( m+icoffa, desca( nb_ ), mycol, iacol,
301 $ npcol )
302 lcm =
ilcm( nprow, npcol )
303 lcmp = lcm / nprow
304 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) )
306 $ m+iroffc, desca( mb_ ), 0, 0, nprow ),
307 $ desca( mb_ ), 0, 0, lcmp ), nqc0 ) ) *
308 $ desca( mb_ ) ) + desca( mb_ ) * desca( mb_ )
309 ELSE
310 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) ) / 2,
311 $ ( mpc0 + nqc0 ) * desca( mb_ ) ) +
312 $ desca( mb_ ) * desca( mb_ )
313 END IF
314
315 work( 1 ) = real( lwmin )
316 lquery = ( lwork.EQ.-1 )
317 IF( .NOT.left .AND. .NOT.
lsame( side,
'R' ) )
THEN
318 info = -1
319 ELSE IF( .NOT.notran .AND. .NOT.
lsame( trans,
'T' ) )
THEN
320 info = -2
321 ELSE IF( k.LT.0 .OR. k.GT.nq ) THEN
322 info = -5
323 ELSE IF( left .AND. desca( nb_ ).NE.descc( mb_ ) ) THEN
324 info = -(900+nb_)
325 ELSE IF( left .AND. icoffa.NE.iroffc ) THEN
326 info = -12
327 ELSE IF( .NOT.left .AND. icoffa.NE.icoffc ) THEN
328 info = -13
329 ELSE IF( .NOT.left .AND. iacol.NE.iccol ) THEN
330 info = -13
331 ELSE IF( .NOT.left .AND. desca( nb_ ).NE.descc( nb_ ) ) THEN
332 info = -(1400+nb_)
333 ELSE IF( ictxt.NE.descc( ctxt_ ) ) THEN
334 info = -(1400+ctxt_)
335 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
336 info = -16
337 END IF
338 END IF
339 IF( left ) THEN
340 idum1( 1 ) = ichar( 'L' )
341 ELSE
342 idum1( 1 ) = ichar( 'R' )
343 END IF
344 idum2( 1 ) = 1
345 IF( notran ) THEN
346 idum1( 2 ) = ichar( 'N' )
347 ELSE
348 idum1( 2 ) = ichar( 'T' )
349 END IF
350 idum2( 2 ) = 2
351 idum1( 3 ) = k
352 idum2( 3 ) = 5
353 IF( lwork.EQ.-1 ) THEN
354 idum1( 4 ) = -1
355 ELSE
356 idum1( 4 ) = 1
357 END IF
358 idum2( 4 ) = 16
359 IF( left ) THEN
360 CALL pchk2mat( k, 5, m, 3, ia, ja, desca, 9, m, 3, n, 4,
361 $ ic, jc, descc, 14, 4, idum1, idum2, info )
362 ELSE
363 CALL pchk2mat( k, 5, n, 4, ia, ja, desca, 9, m, 3, n, 4,
364 $ ic, jc, descc, 14, 4, idum1, idum2, info )
365 END IF
366 END IF
367
368 IF( info.NE.0 ) THEN
369 CALL pxerbla( ictxt,
'PSORMRQ', -info )
370 RETURN
371 ELSE IF( lquery ) THEN
372 RETURN
373 END IF
374
375
376
377 IF( m.EQ.0 .OR. n.EQ.0 .OR. k.EQ.0 )
378 $ RETURN
379
380 CALL pb_topget( ictxt, 'Broadcast', 'Rowwise', rowbtop )
381 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise', colbtop )
382
383 IF( ( left .AND. .NOT.notran ) .OR.
384 $ ( .NOT.left .AND. notran ) ) THEN
385 i1 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
386 $ + 1
387 i2 = ia + k - 1
388 i3 = desca( mb_ )
389 ELSE
390 i1 =
max( ( (ia+k-2) / desca( mb_ ) ) * desca( mb_ ) + 1, ia )
391 i2 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
392 $ + 1
393 i3 = -desca( mb_ )
394 END IF
395
396 IF( left ) THEN
397 ni = n
398 ELSE
399 mi = m
400 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', ' ' )
401 IF( notran ) THEN
402 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'I-ring' )
403 ELSE
404 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'D-ring' )
405 END IF
406 END IF
407
408 IF( notran ) THEN
409 transt = 'T'
410 ELSE
411 transt = 'N'
412 END IF
413
414 IF( ( left .AND. .NOT.notran ) .OR.
415 $ ( .NOT.left .AND. notran ) ) THEN
416 ib = i1 - ia
417 IF( left ) THEN
418 mi = m - k + ib
419 ELSE
420 ni = n - k + ib
421 END IF
422 CALL psormr2( side, trans, mi, ni, ib, a, ia, ja, desca, tau,
423 $ c, ic, jc, descc, work, lwork, iinfo )
424 END IF
425
426 ipw = desca( mb_ )*desca( mb_ ) + 1
427 DO 10 i = i1, i2, i3
428 ib =
min( desca( mb_ ), k-i+ia )
429
430
431
432
433 CALL pslarft(
'Backward',
'Rowwise', nq-k+i+ib-ia, ib,
434 $ a, i, ja, desca, tau, work, work( ipw ) )
435 IF( left ) THEN
436
437
438
439 mi = m - k + i + ib - ia
440 ELSE
441
442
443
444 ni = n - k + i + ib - ia
445 END IF
446
447
448
449 CALL pslarfb( side, transt,
'Backward',
'Rowwise', mi, ni,
450 $ ib, a, i, ja, desca, work, c, ic, jc, descc,
451 $ work( ipw ) )
452 10 CONTINUE
453
454 IF( ( right .AND. tran ) .OR.
455 $ ( left .AND. notran ) ) THEN
456 ib = i2 - ia
457 IF( left ) THEN
458 mi = m - k + ib
459 ELSE
460 ni = n - k + ib
461 END IF
462 CALL psormr2( side, trans, mi, ni, ib, a, ia, ja, desca, tau,
463 $ c, ic, jc, descc, work, lwork, iinfo )
464 END IF
465
466 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', rowbtop )
467 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', colbtop )
468
469 work( 1 ) = real( lwmin )
470
471 RETURN
472
473
474
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 psormr2(side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine pxerbla(ictxt, srname, info)