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
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
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( 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 ) = 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( .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,
'PDORMQR', -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. .NOT.notran ) .OR.
373 $ ( .NOT.left .AND. notran ) ) THEN
374 j1 =
min(
iceil( ja, desca( nb_ ) ) * desca( nb_ ), ja+k-1 )
375 $ + 1
376 j2 = ja+k-1
377 j3 = desca( nb_ )
378 ELSE
379 j1 =
max( ( (ja+k-2) / desca( nb_ ) ) * desca( nb_ ) + 1, ja )
380 j2 =
min(
iceil( ja, desca( nb_ ) ) * desca( nb_ ), ja+k-1 )
381 $ + 1
382 j3 = -desca( nb_ )
383 END IF
384
385 IF( left ) THEN
386 ni = n
387 jcc = jc
388 IF( notran ) THEN
389 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', 'D-ring' )
390 ELSE
391 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', 'I-ring' )
392 END IF
393 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', ' ' )
394 ELSE
395 mi = m
396 icc = ic
397 END IF
398
399
400
401 IF( ( left .AND. .NOT.notran ) .OR. ( .NOT.left .AND. notran ) )
402 $
CALL pdorm2r( side, trans, m, n, j1-ja, a, ia, ja, desca, tau,
403 $ c, ic, jc, descc, work, lwork, iinfo )
404
405 ipw = desca( nb_ ) * desca( nb_ ) + 1
406 DO 10 j = j1, j2, j3
407 jb =
min( desca( nb_ ), k-j+ja )
408
409
410
411
412 CALL pdlarft(
'Forward',
'Columnwise', nq-j+ja, jb, a,
413 $ ia+j-ja, j, desca, tau, work, work( ipw ) )
414 IF( left ) THEN
415
416
417
418 mi = m - j + ja
419 icc = ic + j - ja
420 ELSE
421
422
423
424 ni = n - j + ja
425 jcc = jc + j - ja
426 END IF
427
428
429
430 CALL pdlarfb( side, trans,
'Forward',
'Columnwise', mi, ni,
431 $ jb, a, ia+j-ja, j, desca, work, c, icc, jcc,
432 $ descc, work( ipw ) )
433 10 CONTINUE
434
435
436
437 IF( ( left .AND. notran ) .OR. ( .NOT.left .AND. .NOT.notran ) )
438 $
CALL pdorm2r( side, trans, m, n, j2-ja, a, ia, ja, desca, tau,
439 $ c, ic, jc, descc, work, lwork, iinfo )
440
441 CALL pb_topset( ictxt, 'Broadcast', 'Rowwise', rowbtop )
442 CALL pb_topset( ictxt, 'Broadcast', 'Columnwise', colbtop )
443
444 work( 1 ) = dble( lwmin )
445
446 RETURN
447
448
449
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 pdorm2r(side, trans, m, n, k, a, ia, ja, desca, tau, c, ic, jc, descc, work, lwork, info)
subroutine pxerbla(ictxt, srname, info)