3
4
5
6
7
8
9
10 INTEGER IA, JA, INFO, LWORK, M, N
11
12
13 INTEGER DESCA( * ), IPIV( * )
14 DOUBLE PRECISION A( * ), TAU( * ), WORK( * )
15
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 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
186 $ LLD_, MB_, M_, NB_, N_, RSRC_
187 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
188 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
189 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
190 DOUBLE PRECISION ONE, ZERO
191 parameter( one = 1.0d+0, zero = 0.0d+0 )
192
193
194 LOGICAL LQUERY
195 INTEGER I, IACOL, IAROW, ICOFF, ICTXT, ICURROW,
196 $ ICURCOL, II, IIA, IOFFA, IPN, IPCOL, IPW,
197 $ IROFF, ITEMP, J, JB, JJ, JJA, JJPVT, JN, KB,
198 $ K, KK, KSTART, KSTEP, LDA, LL, LWMIN, MN, MP,
199 $ MYCOL, MYROW, NPCOL, NPROW, NQ, NQ0, PVT
200 DOUBLE PRECISION AJJ, ALPHA, TEMP, TEMP2, TOL3Z
201
202
203 INTEGER DESCN( DLEN_ ), IDUM1( 1 ), IDUM2( 1 )
204
205
207 $ dgebr2d, dgebs2d, dgerv2d,
208 $ dgesd2d, dlarfg, dswap, igerv2d,
212
213
214 INTEGER ICEIL, INDXG2P, NUMROC
216 DOUBLE PRECISION DLAMCH
218
219
220 INTRINSIC abs, dble, idint,
max,
min, mod, sqrt
221
222
223
224
225
226 ictxt = desca( ctxt_ )
227 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
228
229
230
231 info = 0
232 IF( nprow.EQ.-1 ) THEN
233 info = -(600+ctxt_)
234 ELSE
235 CALL chk1mat( m, 1, n, 2, ia, ja, desca, 6, info )
236 IF( info.EQ.0 ) THEN
237 iroff = mod( ia-1, desca( mb_ ) )
238 icoff = mod( ja-1, desca( nb_ ) )
239 iarow =
indxg2p( ia, desca( mb_ ), myrow, desca( rsrc_ ),
240 $ nprow )
241 iacol =
indxg2p( ja, desca( nb_ ), mycol, desca( csrc_ ),
242 $ npcol )
243 mp =
numroc( m+iroff, desca( mb_ ), myrow, iarow, nprow )
244 nq =
numroc( n+icoff, desca( nb_ ), mycol, iacol, npcol )
245 nq0 =
numroc( ja+n-1, desca( nb_ ), mycol, desca( csrc_ ),
246 $ npcol )
247 lwmin =
max( 3, mp + nq ) + nq0 + nq
248
249 work( 1 ) = dble( lwmin )
250 lquery = ( lwork.EQ.-1 )
251 IF( lwork.LT.lwmin .AND. .NOT.lquery )
252 $ info = -10
253 END IF
254 IF( lwork.EQ.-1 ) THEN
255 idum1( 1 ) = -1
256 ELSE
257 idum1( 1 ) = 1
258 END IF
259 idum2( 1 ) = 10
260 CALL pchk1mat( m, 1, n, 2, ia, ja, desca, 6, 1, idum1, idum2,
261 $ info )
262 END IF
263
264 IF( info.NE.0 ) THEN
265 CALL pxerbla( ictxt,
'PDGEQPF', -info )
266 RETURN
267 ELSE IF( lquery ) THEN
268 RETURN
269 END IF
270
271
272
273 IF( m.EQ.0 .OR. n.EQ.0 )
274 $ RETURN
275
276 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
277 $ iarow, iacol )
278 IF( myrow.EQ.iarow )
279 $ mp = mp - iroff
280 IF( mycol.EQ.iacol )
281 $ nq = nq - icoff
283 tol3z = sqrt(
dlamch(
'Epsilon') )
284
285
286
287 lda = desca( lld_ )
288 jn =
min(
iceil( ja, desca( nb_ ) ) * desca( nb_ ), ja+n-1 )
289 kstep = npcol * desca( nb_ )
290
291 IF( mycol.EQ.iacol ) THEN
292
293
294
295 jb = jn - ja + 1
296 DO 10 ll = jja, jja+jb-1
297 ipiv( ll ) = ja + ll - jja
298 10 CONTINUE
299 kstart = jn + kstep - desca( nb_ )
300
301
302
303 DO 30 kk = jja+jb, jja+nq-1, desca( nb_ )
304 kb =
min( jja+nq-kk, desca( nb_ ) )
305 DO 20 ll = kk, kk+kb-1
306 ipiv( ll ) = kstart+ll-kk+1
307 20 CONTINUE
308 kstart = kstart + kstep
309 30 CONTINUE
310 ELSE
311 kstart = jn + ( mod( mycol-iacol+npcol, npcol )-1 )*
312 $ desca( nb_ )
313 DO 50 kk = jja, jja+nq-1, desca( nb_ )
314 kb =
min( jja+nq-kk, desca( nb_ ) )
315 DO 40 ll = kk, kk+kb-1
316 ipiv( ll ) = kstart+ll-kk+1
317 40 CONTINUE
318 kstart = kstart + kstep
319 50 CONTINUE
320 END IF
321
322
323
324 CALL descset( descn, 1, desca( n_ ), 1, desca( nb_ ), myrow,
325 $ desca( csrc_ ), ictxt, 1 )
326
327 ipn = 1
328 ipw = ipn + nq0 + nq
329 jj = ipn + jja - 1
330 IF( mycol.EQ.iacol ) THEN
331 DO 60 kk = 0, jb-1
332 CALL pdnrm2( m, work( jj+kk ), a, ia, ja+kk, desca, 1 )
333 work( nq+jj+kk ) = work( jj+kk )
334 60 CONTINUE
335 jj = jj + jb
336 END IF
337 icurcol = mod( iacol+1, npcol )
338
339
340
341 DO 80 j = jn+1, ja+n-1, desca( nb_ )
342 jb =
min( ja+n-j, desca( nb_ ) )
343
344 IF( mycol.EQ.icurcol ) THEN
345 DO 70 kk = 0, jb-1
346 CALL pdnrm2( m, work( jj+kk ), a, ia, j+kk, desca, 1 )
347 work( nq+jj+kk ) = work( jj+kk )
348 70 CONTINUE
349 jj = jj + jb
350 END IF
351 icurcol = mod( icurcol+1, npcol )
352 80 CONTINUE
353
354
355
356 DO 120 j = ja, ja+mn-1
357 i = ia + j - ja
358
359 CALL infog1l( j, desca( nb_ ), npcol, mycol, desca( csrc_ ),
360 $ jj, icurcol )
361 k = ja + n - j
362 IF( k.GT.1 ) THEN
363 CALL pdamax( k, temp, pvt, work( ipn ), 1, j, descn,
364 $ descn( m_ ) )
365 ELSE
366 pvt = j
367 END IF
368 IF( j.NE.pvt ) THEN
369 CALL infog1l( pvt, desca( nb_ ), npcol, mycol,
370 $ desca( csrc_ ), jjpvt, ipcol )
371 IF( icurcol.EQ.ipcol ) THEN
372 IF( mycol.EQ.icurcol ) THEN
373 CALL dswap( mp, a( iia+(jj-1)*lda ), 1,
374 $ a( iia+(jjpvt-1)*lda ), 1 )
375 itemp = ipiv( jjpvt )
376 ipiv( jjpvt ) = ipiv( jj )
377 ipiv( jj ) = itemp
378 work( ipn+jjpvt-1 ) = work( ipn+jj-1 )
379 work( ipn+nq+jjpvt-1 ) = work( ipn+nq+jj-1 )
380 END IF
381 ELSE
382 IF( mycol.EQ.icurcol ) THEN
383
384 CALL dgesd2d( ictxt, mp, 1, a( iia+(jj-1)*lda ), lda,
385 $ myrow, ipcol )
386 work( ipw ) = dble( ipiv( jj ) )
387 work( ipw+1 ) = work( ipn + jj - 1 )
388 work( ipw+2 ) = work( ipn + nq + jj - 1 )
389 CALL dgesd2d( ictxt, 3, 1, work( ipw ), 3, myrow,
390 $ ipcol )
391
392 CALL dgerv2d( ictxt, mp, 1, a( iia+(jj-1)*lda ), lda,
393 $ myrow, ipcol )
394 CALL igerv2d( ictxt, 1, 1, ipiv( jj ), 1, myrow,
395 $ ipcol )
396
397 ELSE IF( mycol.EQ.ipcol ) THEN
398
399 CALL dgesd2d( ictxt, mp, 1, a( iia+(jjpvt-1)*lda ),
400 $ lda, myrow, icurcol )
401 CALL igesd2d( ictxt, 1, 1, ipiv( jjpvt ), 1, myrow,
402 $ icurcol )
403
404 CALL dgerv2d( ictxt, mp, 1, a( iia+(jjpvt-1)*lda ),
405 $ lda, myrow, icurcol )
406 CALL dgerv2d( ictxt, 3, 1, work( ipw ), 3, myrow,
407 $ icurcol )
408 ipiv( jjpvt ) = idint( work( ipw ) )
409 work( ipn+jjpvt-1 ) = work( ipw+1 )
410 work( ipn+nq+jjpvt-1 ) = work( ipw+2 )
411
412 END IF
413
414 END IF
415
416 END IF
417
418
419
420 CALL infog1l( i, desca( mb_ ), nprow, myrow, desca( rsrc_ ),
421 $ ii, icurrow )
422 IF( desca( m_ ).EQ.1 ) THEN
423 IF( myrow.EQ.icurrow ) THEN
424 IF( mycol.EQ.icurcol ) THEN
425 ioffa = ii+(jj-1)*desca( lld_ )
426 ajj = a( ioffa )
427 CALL dlarfg( 1, ajj, a( ioffa ), 1, tau( jj ) )
428 IF( n.GT.1 ) THEN
429 alpha = one - tau( jj )
430 CALL dgebs2d( ictxt, 'Rowwise', ' ', 1, 1, alpha,
431 $ 1 )
432 CALL dscal( nq-jj, alpha, a( ioffa+desca( lld_ ) ),
433 $ desca( lld_ ) )
434 END IF
435 CALL dgebs2d( ictxt, 'Columnwise', ' ', 1, 1,
436 $ tau( jj ), 1 )
437 a( ioffa ) = ajj
438 ELSE
439 IF( n.GT.1 ) THEN
440 CALL dgebr2d( ictxt, 'Rowwise', ' ', 1, 1, alpha,
441 $ 1, icurrow, icurcol )
442 CALL dscal( nq-jj+1, alpha, a( i ), desca( lld_ ) )
443 END IF
444 END IF
445 ELSE IF( mycol.EQ.icurcol ) THEN
446 CALL dgebr2d( ictxt, 'Columnwise', ' ', 1, 1, tau( jj ),
447 $ 1, icurrow, icurcol )
448 END IF
449
450 ELSE
451
452 CALL pdlarfg( m-j+ja, ajj, i, j, a,
min( i+1, ia+m-1 ), j,
453 $ desca, 1, tau )
454 IF( j.LT.ja+n-1 ) THEN
455
456
457
458 CALL pdelset( a, i, j, desca, one )
459 CALL pdlarf(
'Left', m-j+ja, ja+n-1-j, a, i, j, desca,
460 $ 1, tau, a, i, j+1, desca, work( ipw ) )
461 END IF
462 CALL pdelset( a, i, j, desca, ajj )
463
464 END IF
465
466
467
468 IF( mycol.EQ.icurcol )
469 $ jj = jj + 1
470 IF( mod( j, desca( nb_ ) ).EQ.0 )
471 $ icurcol = mod( icurcol+1, npcol )
472 IF( (jja+nq-jj).GT.0 ) THEN
473 IF( myrow.EQ.icurrow ) THEN
474 CALL dgebs2d( ictxt, 'Columnwise', ' ', 1, jja+nq-jj,
475 $ a( ii+(
min( jja+nq-1, jj )-1 )*lda ),
476 $ lda )
477 CALL dcopy( jja+nq-jj, a( ii+(
min( jja+nq-1, jj )
478 $ -1)*lda ), lda, work( ipw+
min( jja+nq-1,
479 $ jj )-1 ), 1 )
480 ELSE
481 CALL dgebr2d( ictxt, 'Columnwise', ' ', jja+nq-jj, 1,
482 $ work( ipw+
min( jja+nq-1, jj )-1 ),
483 $
max( 1, nq ), icurrow, mycol )
484 END IF
485 END IF
486
487 jn =
min(
iceil( j+1, desca( nb_ ) ) * desca( nb_ ),
488 $ ja + n - 1 )
489 IF( mycol.EQ.icurcol ) THEN
490 DO 90 ll = jj-1, jj + jn - j - 2
491 IF( work( ipn+ll ).NE.zero ) THEN
492 temp = abs( work( ipw+ll ) ) / work( ipn+ll )
493 temp =
max( zero, ( one+temp )*( one-temp ) )
494 temp2 = temp*( work( ipn+ll ) / work( ipn+nq+ll ) )**2
495 IF( temp2.LE.tol3z ) THEN
496 IF( ia+m-1.GT.i ) THEN
497 CALL pdnrm2( ia+m-i-1, work( ipn+ll ), a, i+1,
498 $ j+ll-jj+2, desca, 1 )
499 work( ipn+nq+ll ) = work( ipn+ll )
500 ELSE
501 work( ipn+ll ) = zero
502 work( ipn+nq+ll ) = zero
503 END IF
504 ELSE
505 work( ipn+ll ) = work( ipn+ll ) * sqrt( temp )
506 END IF
507 END IF
508 90 CONTINUE
509 jj = jj + jn - j
510 END IF
511 icurcol = mod( icurcol+1, npcol )
512
513 DO 110 k = jn+1, ja+n-1, desca( nb_ )
514 kb =
min( ja+n-k, desca( nb_ ) )
515
516 IF( mycol.EQ.icurcol ) THEN
517 DO 100 ll = jj-1, jj+kb-2
518 IF( work( ipn+ll ).NE.zero ) THEN
519 temp = abs( work( ipw+ll ) ) / work( ipn+ll )
520 temp =
max( zero, ( one+temp )*( one-temp ) )
521 temp2 = temp*
522 $ ( work( ipn+ll ) / work( ipn+nq+ll ) )**2
523 IF( temp2.LE.tol3z ) THEN
524 IF( ia+m-1.GT.i ) THEN
525 CALL pdnrm2( ia+m-i-1, work( ipn+ll ), a,
526 $ i+1, k+ll-jj+1, desca, 1 )
527 work( ipn+nq+ll ) = work( ipn+ll )
528 ELSE
529 work( ipn+ll ) = zero
530 work( ipn+nq+ll ) = zero
531 END IF
532 ELSE
533 work( ipn+ll ) = work( ipn+ll ) * sqrt( temp )
534 END IF
535 END IF
536 100 CONTINUE
537 jj = jj + kb
538 END IF
539 icurcol = mod( icurcol+1, npcol )
540
541 110 CONTINUE
542
543 120 CONTINUE
544
545 work( 1 ) = dble( lwmin )
546
547 RETURN
548
549
550
subroutine chk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, info)
subroutine descset(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld)
integer function iceil(inum, idenom)
integer function indxg2p(indxglob, nb, iproc, isrcproc, nprocs)
subroutine infog1l(gindx, nb, nprocs, myroc, isrcproc, lindx, rocsrc)
subroutine infog2l(grindx, gcindx, desc, nprow, npcol, myrow, mycol, lrindx, lcindx, rsrc, csrc)
integer function numroc(n, nb, iproc, isrcproc, nprocs)
subroutine pchk1mat(ma, mapos0, na, napos0, ia, ja, desca, descapos0, nextra, ex, expos, info)
subroutine pdelset(a, ia, ja, desca, alpha)
subroutine pdlarf(side, m, n, v, iv, jv, descv, incv, tau, c, ic, jc, descc, work)
subroutine pdlarfg(n, alpha, iax, jax, x, ix, jx, descx, incx, tau)
subroutine pxerbla(ictxt, srname, info)