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 DOUBLE PRECISION 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
239
240
241 LOGICAL LSAME
242 INTEGER ICEIL, ILCM, INDXG2P, NUMROC
244
245
246 INTRINSIC dble, ichar,
max,
min, mod
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( k, 5, m, 3, ia, ja, desca, 9, info )
269 ELSE
270 nq = n
271 CALL chk1mat( k, 5, n, 4, 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 icoffa = mod( ja-1, desca( nb_ ) )
276 iroffc = mod( ic-1, descc( mb_ ) )
277 icoffc = mod( jc-1, descc( nb_ ) )
278 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
279 $ npcol )
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 mqa0 =
numroc( m+icoffa, desca( nb_ ), mycol, iacol,
289 $ npcol )
290 lcm =
ilcm( nprow, npcol )
291 lcmp = lcm / nprow
292 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) )
294 $ m+iroffc, desca( mb_ ), 0, 0, nprow ),
295 $ desca( mb_ ), 0, 0, lcmp ), nqc0 ) ) *
296 $ desca( mb_ ) ) + desca( mb_ ) * desca( mb_ )
297 ELSE
298 lwmin =
max( ( desca( mb_ ) * ( desca( mb_ ) - 1 ) ) / 2,
299 $ ( mpc0 + nqc0 ) * desca( mb_ ) ) +
300 $ desca( mb_ ) * desca( mb_ )
301 END IF
302
303 work( 1 ) = dble( 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( left .AND. desca( nb_ ).NE.descc( mb_ ) ) THEN
312 info = -(900+nb_)
313 ELSE IF( left .AND. icoffa.NE.iroffc ) THEN
314 info = -12
315 ELSE IF( .NOT.left .AND. icoffa.NE.icoffc ) THEN
316 info = -13
317 ELSE IF( .NOT.left .AND. iacol.NE.iccol ) THEN
318 info = -13
319 ELSE IF( .NOT.left .AND. desca( nb_ ).NE.descc( nb_ ) ) THEN
320 info = -(1400+nb_)
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 IF( left ) THEN
328 idum1( 1 ) = ichar( 'L' )
329 ELSE
330 idum1( 1 ) = ichar( 'R' )
331 END IF
332 idum2( 1 ) = 1
333 IF( notran ) THEN
334 idum1( 2 ) = ichar( 'N' )
335 ELSE
336 idum1( 2 ) = ichar( 'T' )
337 END IF
338 idum2( 2 ) = 2
339 idum1( 3 ) = k
340 idum2( 3 ) = 5
341 IF( lwork.EQ.-1 ) THEN
342 idum1( 4 ) = -1
343 ELSE
344 idum1( 4 ) = 1
345 END IF
346 idum2( 4 ) = 16
347 IF( left ) THEN
348 CALL pchk2mat( k, 5, m, 3, ia, ja, desca, 9, m, 3, n, 4, ic,
349 $ jc, descc, 14, 4, idum1, idum2, info )
350 ELSE
351 CALL pchk2mat( k, 5, n, 4, ia, ja, desca, 9, m, 3, n, 4, ic,
352 $ jc, descc, 14, 4, idum1, idum2, info )
353 END IF
354 END IF
355
356 IF( info.NE.0 ) THEN
357 CALL pxerbla( ictxt,
'PDORMLQ', -info )
358 RETURN
359 ELSE IF( lquery ) THEN
360 RETURN
361 END IF
362
363
364
365 IF( m.EQ.0 .OR. n.EQ.0 .OR. k.EQ.0 )
366 $ RETURN
367
368 CALL pb_topget( ictxt, 'Broadcast', 'Rowwise', rowbtop )
369 CALL pb_topget( ictxt, 'Broadcast', 'Columnwise', colbtop )
370
371 IF( ( left .AND. notran ) .OR.
372 $ ( .NOT.left .AND. .NOT.notran ) ) THEN
373 i1 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
374 $ + 1
375 i2 = ia + k - 1
376 i3 = desca( mb_ )
377 ELSE
378 i1 =
max( ( (ia+k-2) / desca( mb_ ) ) * desca( mb_ ) + 1, ia )
379 i2 =
min(
iceil( ia, desca( mb_ ) ) * desca( mb_ ), ia+k-1 )
380 $ + 1
381 i3 = -desca( mb_ )
382 END IF
383
384 IF( left ) THEN
385 ni = n
386 jcc = jc
387 ELSE
388 mi = m
389 icc = ic
390 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', ' ' )
391 IF( notran ) THEN
392 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'D-ring' )
393 ELSE
394 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', 'I-ring' )
395 END IF
396 END IF
397
398 IF( notran ) THEN
399 transt = 'T'
400 ELSE
401 transt = 'N'
402 END IF
403
404 IF( ( left .AND. notran ) .OR. ( .NOT.left .AND. .NOT.notran ) )
405 $
CALL pdorml2( side, trans, m, n, i1-ia, a, ia, ja, desca, tau,
406 $ c, ic, jc, descc, work, lwork, iinfo )
407
408 ipw = desca( mb_ ) * desca( mb_ ) + 1
409 DO 10 i = i1, i2, i3
410 ib =
min( desca( mb_ ), k-i+ia )
411
412
413
414
415 CALL pdlarft(
'Forward',
'Rowwise', nq-i+ia, ib, a, i, ja+i-ia,
416 $ desca, tau, work, work( ipw ) )
417 IF( left ) THEN
418
419
420
421 mi = m - i + ia
422 icc = ic + i - ia
423 ELSE
424
425
426
427 ni = n - i + ia
428 jcc = jc + i - ia
429 END IF
430
431
432
433 CALL pdlarfb( side, transt,
'Forward',
'Rowwise', mi, ni, ib,
434 $ a, i, ja+i-ia, desca, work, c, icc, jcc, descc,
435 $ work( ipw ) )
436 10 CONTINUE
437
438 IF( ( left .AND. .NOT.notran ) .OR. ( .NOT.left .AND. notran ) )
439 $
CALL pdorml2( side, trans, m, n, i2-ia, 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 ) = 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 pdlarfb(side, trans, direct, storev, m, n, k, v, iv, jv, descv, t, c, ic, jc, descc, work)
subroutine pdlarft(direct, storev, n, k, v, iv, jv, descv, tau, t, work)
subroutine pdorml2(side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine pxerbla(ictxt, srname, info)