SCALAPACK 2.2.2
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
pcgebdrv.f
Go to the documentation of this file.
1 SUBROUTINE pcgebdrv( M, N, A, IA, JA, DESCA, D, E, TAUQ, TAUP,
2 $ WORK, INFO )
3*
4* -- ScaLAPACK routine (version 1.7) --
5* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
6* and University of California, Berkeley.
7* May 1, 1997
8*
9* .. Scalar Arguments ..
10 INTEGER INFO, IA, JA, M, N
11* ..
12* .. Array Arguments ..
13 INTEGER DESCA( * )
14 REAL D( * ), E( * )
15 COMPLEX A( * ), TAUP( * ), TAUQ( * ), WORK( * )
16* ..
17*
18* Purpose
19* =======
20*
21* PCGEBDRV computes sub( A ) = A(IA:IA+M-1,JA:JA+N-1) from sub( A ),
22* Q, P returned by PCGEBRD:
23*
24* sub( A ) := Q * B * P'.
25*
26* Notes
27* =====
28*
29* Each global data object is described by an associated description
30* vector. This vector stores the information required to establish
31* the mapping between an object element and its corresponding process
32* and memory location.
33*
34* Let A be a generic term for any 2D block cyclicly distributed array.
35* Such a global array has an associated description vector DESCA.
36* In the following comments, the character _ should be read as
37* "of the global array".
38*
39* NOTATION STORED IN EXPLANATION
40* --------------- -------------- --------------------------------------
41* DTYPE_A(global) DESCA( DTYPE_ )The descriptor type. In this case,
42* DTYPE_A = 1.
43* CTXT_A (global) DESCA( CTXT_ ) The BLACS context handle, indicating
44* the BLACS process grid A is distribu-
45* ted over. The context itself is glo-
46* bal, but the handle (the integer
47* value) may vary.
48* M_A (global) DESCA( M_ ) The number of rows in the global
49* array A.
50* N_A (global) DESCA( N_ ) The number of columns in the global
51* array A.
52* MB_A (global) DESCA( MB_ ) The blocking factor used to distribute
53* the rows of the array.
54* NB_A (global) DESCA( NB_ ) The blocking factor used to distribute
55* the columns of the array.
56* RSRC_A (global) DESCA( RSRC_ ) The process row over which the first
57* row of the array A is distributed.
58* CSRC_A (global) DESCA( CSRC_ ) The process column over which the
59* first column of the array A is
60* distributed.
61* LLD_A (local) DESCA( LLD_ ) The leading dimension of the local
62* array. LLD_A >= MAX(1,LOCr(M_A)).
63*
64* Let K be the number of rows or columns of a distributed matrix,
65* and assume that its process grid has dimension p x q.
66* LOCr( K ) denotes the number of elements of K that a process
67* would receive if K were distributed over the p processes of its
68* process column.
69* Similarly, LOCc( K ) denotes the number of elements of K that a
70* process would receive if K were distributed over the q processes of
71* its process row.
72* The values of LOCr() and LOCc() may be determined via a call to the
73* ScaLAPACK tool function, NUMROC:
74* LOCr( M ) = NUMROC( M, MB_A, MYROW, RSRC_A, NPROW ),
75* LOCc( N ) = NUMROC( N, NB_A, MYCOL, CSRC_A, NPCOL ).
76* An upper bound for these quantities may be computed by:
77* LOCr( M ) <= ceil( ceil(M/MB_A)/NPROW )*MB_A
78* LOCc( N ) <= ceil( ceil(N/NB_A)/NPCOL )*NB_A
79*
80* Arguments
81* =========
82*
83* M (global input) INTEGER
84* The number of rows to be operated on, i.e. the number of rows
85* of the distributed submatrix sub( A ). M >= 0.
86*
87* N (global input) INTEGER
88* The number of columns to be operated on, i.e. the number of
89* columns of the distributed submatrix sub( A ). N >= 0.
90*
91* A (local input/local output) COMPLEX pointer into the
92* local memory to an array of dimension (LLD_A, LOCc(JA+N-1)).
93* On entry, this array contains the local pieces of sub( A )
94* as returned by PCGEBRD. On exit, the original distribu-
95* ted matrix sub( A ) is restored.
96*
97* IA (global input) INTEGER
98* The row index in the global array A indicating the first
99* row of sub( A ).
100*
101* JA (global input) INTEGER
102* The column index in the global array A indicating the
103* first column of sub( A ).
104*
105* DESCA (global and local input) INTEGER array of dimension DLEN_.
106* The array descriptor for the distributed matrix A.
107*
108* D (local input) REAL array, dimension
109* LOCc(JA+MIN(M,N)-1) if M >= N; LOCr(IA+MIN(M,N)-1) otherwise.
110* The distributed diagonal elements of the bidiagonal matrix
111* B: D(i) = A(i,i). D is tied to the distributed matrix A.
112*
113* E (local input) REAL array, dimension
114* LOCr(IA+MIN(M,N)-1) if M >= N; LOCc(JA+MIN(M,N)-2) otherwise.
115* The distributed off-diagonal elements of the bidiagonal
116* distributed matrix B:
117* if m >= n, E(i) = A(i,i+1) for i = 1,2,...,n-1;
118* if m < n, E(i) = A(i+1,i) for i = 1,2,...,m-1.
119* E is tied to the distributed matrix A.
120*
121* TAUQ (local input) COMPLEX array dimension
122* LOCc(JA+MIN(M,N)-1). The scalar factors of the elementary
123* reflectors which represent the unitary matrix Q. TAUQ is
124* tied to the distributed matrix A. See Further Details.
125*
126* TAUP (local input) COMPLEX array, dimension
127* LOCr(IA+MIN(M,N)-1). The scalar factors of the elementary
128* reflectors which represent the unitary matrix P. TAUP is
129* tied to the distributed matrix A. See Further Details.
130*
131* WORK (local workspace) COMPLEX array, dimension (LWORK)
132* LWORK >= 2*NB*( MP + NQ + NB )
133*
134* where NB = MB_A = NB_A,
135* IROFFA = MOD( IA-1, NB ), ICOFFA = MOD( JA-1, NB ),
136* IAROW = INDXG2P( IA, NB, MYROW, RSRC_A, NPROW ),
137* IACOL = INDXG2P( JA, NB, MYCOL, CSRC_A, NPCOL ),
138* MP = NUMROC( M+IROFFA, NB, MYROW, IAROW, NPROW ),
139* NQ = NUMROC( N+ICOFFA, NB, MYCOL, IACOL, NPCOL ).
140*
141* INDXG2P and NUMROC are ScaLAPACK tool functions;
142* MYROW, MYCOL, NPROW and NPCOL can be determined by calling
143* the subroutine BLACS_GRIDINFO.
144*
145* INFO (global output) INTEGER
146* On exit, if INFO <> 0, a discrepancy has been found between
147* the diagonal and off-diagonal elements of A and the copies
148* contained in the arrays D and E.
149*
150* =====================================================================
151*
152* .. Parameters ..
153 INTEGER BLOCK_CYCLIC_2D, CSRC_, CTXT_, DLEN_, DTYPE_,
154 $ lld_, mb_, m_, nb_, n_, rsrc_
155 parameter( block_cyclic_2d = 1, dlen_ = 9, dtype_ = 1,
156 $ ctxt_ = 2, m_ = 3, n_ = 4, mb_ = 5, nb_ = 6,
157 $ rsrc_ = 7, csrc_ = 8, lld_ = 9 )
158 REAL REIGHT, RZERO
159 parameter( reight = 8.0e+0, rzero = 0.0e+0 )
160 COMPLEX ONE, ZERO
161 parameter( one = ( 1.0e+0, 0.0e+0 ),
162 $ zero = ( 0.0e+0, 0.0e+0 ) )
163* ..
164* .. Local Scalars ..
165 INTEGER I, IACOL, IAROW, ICTXT, IIA, IL, IPTP, IPTQ,
166 $ ipv, ipw, ipwk, ioff, iv, j, jb, jja, jl, jv,
167 $ k, mn, mp, mycol, myrow, nb, npcol, nprow, nq
168 REAL ADDBND, D2, E2
169 COMPLEX D1, E1
170* ..
171* .. Local Arrays ..
172 INTEGER DESCD( DLEN_ ), DESCE( DLEN_ ), DESCV( DLEN_ ),
173 $ descw( dlen_ )
174* ..
175* .. External Subroutines ..
176 EXTERNAL blacs_gridinfo, descset, igsum2d, infog2l,
179* ..
180* .. External Functions ..
181 INTEGER INDXG2P, NUMROC
182 REAL PSLAMCH
183 EXTERNAL indxg2p, numroc, pslamch
184* ..
185* .. Intrinsic Functions ..
186 INTRINSIC abs, cmplx, max, min, mod
187* ..
188* .. Executable Statements ..
189*
190* Get grid parameters
191*
192 ictxt = desca( ctxt_ )
193 CALL blacs_gridinfo( ictxt, nprow, npcol, myrow, mycol )
194*
195 info = 0
196 nb = desca( mb_ )
197 ioff = mod( ia-1, nb )
198 CALL infog2l( ia, ja, desca, nprow, npcol, myrow, mycol, iia, jja,
199 $ iarow, iacol )
200 mp = numroc( m+ioff, nb, myrow, iarow, nprow )
201 nq = numroc( n+ioff, nb, mycol, iacol, npcol )
202 ipv = 1
203 ipw = ipv + mp*nb
204 iptp = ipw + nq*nb
205 iptq = iptp + nb*nb
206 ipwk = iptq + nb*nb
207*
208 iv = 1
209 jv = 1
210 mn = min( m, n )
211 il = max( ( (ia+mn-2) / nb )*nb + 1, ia )
212 jl = max( ( (ja+mn-2) / nb )*nb + 1, ja )
213 iarow = indxg2p( il, nb, myrow, desca( rsrc_ ), nprow )
214 iacol = indxg2p( jl, nb, mycol, desca( csrc_ ), npcol )
215 CALL descset( descv, ia+m-il, nb, nb, nb, iarow, iacol, ictxt,
216 $ max( 1, mp ) )
217 CALL descset( descw, nb, ja+n-jl, nb, nb, iarow, iacol, ictxt,
218 $ nb )
219*
220 addbnd = reight * pslamch( ictxt, 'eps' )
221*
222* When A is an upper bidiagonal form
223*
224 IF( m.GE.n ) THEN
225*
226 CALL descset( descd, 1, ja+mn-1, 1, desca( nb_ ), myrow,
227 $ desca( csrc_ ), desca( ctxt_ ), 1 )
228 CALL descset( desce, ia+mn-1, 1, desca( mb_ ), 1,
229 $ desca( rsrc_ ), mycol, desca( ctxt_ ),
230 $ desca( lld_ ) )
231*
232 DO 10 j = 0, mn-1
233 d1 = zero
234 e1 = zero
235 d2 = rzero
236 e2 = rzero
237 CALL pselget( ' ', ' ', d2, d, 1, ja+j, descd )
238 CALL pcelget( 'Columnwise', ' ', d1, a, ia+j, ja+j, desca )
239 IF( j.LT.(mn-1) ) THEN
240 CALL pselget( ' ', ' ', e2, e, ia+j, 1, desce )
241 CALL pcelget( 'Rowwise', ' ', e1, a, ia+j, ja+j+1,
242 $ desca )
243 END IF
244*
245 IF( ( abs( d1 - cmplx( d2 ) ).GT.( abs( d2 )*addbnd ) ) .OR.
246 $ ( abs( e1 - cmplx( e2 ) ).GT.( abs( e2 )*addbnd ) ) )
247 $ info = info + 1
248 10 CONTINUE
249*
250 DO 20 j = jl, ja+nb-ioff, -nb
251 jb = min( ja+n-j, nb )
252 i = ia + j - ja
253 k = i - ia + 1
254*
255* Compute upper triangular matrix TQ from TAUQ.
256*
257 CALL pclarft( 'Forward', 'Columnwise', m-k+1, jb, a, i, j,
258 $ desca, tauq, work( iptq ), work( ipwk ) )
259*
260* Copy Householder vectors into workspace.
261*
262 CALL pclacpy( 'Lower', m-k+1, jb, a, i, j, desca,
263 $ work( ipv ), iv, jv, descv )
264 CALL pclaset( 'Upper', m-k+1, jb, zero, one, work( ipv ),
265 $ iv, jv, descv )
266*
267* Zero out the strict lower triangular part of A.
268*
269 CALL pclaset( 'Lower', m-k, jb, zero, zero, a, i+1, j,
270 $ desca )
271*
272* Compute upper triangular matrix TP from TAUP.
273*
274 CALL pclarft( 'Forward', 'Rowwise', n-k, jb, a, i, j+1,
275 $ desca, taup, work( iptp ), work( ipwk ) )
276*
277* Copy Householder vectors into workspace.
278*
279 CALL pclacpy( 'Upper', jb, n-k, a, i, j+1, desca,
280 $ work( ipw ), iv, jv+1, descw )
281 CALL pclaset( 'Lower', jb, n-k, zero, one, work( ipw ), iv,
282 $ jv+1, descw )
283*
284* Zero out the strict+1 upper triangular part of A.
285*
286 CALL pclaset( 'Upper', jb, n-k-1, zero, zero, a, i, j+2,
287 $ desca )
288*
289* Apply block Householder transformation from Left.
290*
291 CALL pclarfb( 'Left', 'No transpose', 'Forward',
292 $ 'Columnwise', m-k+1, n-k+1, jb, work( ipv ),
293 $ iv, jv, descv, work( iptq ), a, i, j, desca,
294 $ work( ipwk ) )
295*
296* Apply block Householder transformation from Right.
297*
298 CALL pclarfb( 'Right', 'Conjugate transpose', 'Forward',
299 $ 'Rowwise', m-k+1, n-k, jb, work( ipw ), iv,
300 $ jv+1, descw, work( iptp ), a, i, j+1, desca,
301 $ work( ipwk ) )
302*
303 descv( m_ ) = descv( m_ ) + nb
304 descv( rsrc_ ) = mod( descv( rsrc_ ) + nprow - 1, nprow )
305 descv( csrc_ ) = mod( descv( csrc_ ) + npcol - 1, npcol )
306 descw( n_ ) = descw( n_ ) + nb
307 descw( rsrc_ ) = descv( rsrc_ )
308 descw( csrc_ ) = descv( csrc_ )
309*
310 20 CONTINUE
311*
312* Handle first block separately
313*
314 jb = min( n, nb - ioff )
315 iv = ioff + 1
316 jv = ioff + 1
317*
318* Compute upper triangular matrix TQ from TAUQ.
319*
320 CALL pclarft( 'Forward', 'Columnwise', m, jb, a, ia, ja, desca,
321 $ tauq, work( iptq ), work( ipwk ) )
322*
323* Copy Householder vectors into workspace.
324*
325 CALL pclacpy( 'Lower', m, jb, a, ia, ja, desca, work( ipv ),
326 $ iv, jv, descv )
327 CALL pclaset( 'Upper', m, jb, zero, one, work( ipv ), iv, jv,
328 $ descv )
329*
330* Zero out the strict lower triangular part of A.
331*
332 CALL pclaset( 'Lower', m-1, jb, zero, zero, a, ia+1, ja,
333 $ desca )
334*
335* Compute upper triangular matrix TP from TAUP.
336*
337 CALL pclarft( 'Forward', 'Rowwise', n-1, jb, a, ia, ja+1,
338 $ desca, taup, work( iptp ), work( ipwk ) )
339*
340* Copy Householder vectors into workspace.
341*
342 CALL pclacpy( 'Upper', jb, n-1, a, ia, ja+1, desca,
343 $ work( ipw ), iv, jv+1, descw )
344 CALL pclaset( 'Lower', jb, n-1, zero, one, work( ipw ), iv,
345 $ jv+1, descw )
346*
347* Zero out the strict+1 upper triangular part of A.
348*
349 CALL pclaset( 'Upper', jb, n-2, zero, zero, a, ia, ja+2,
350 $ desca )
351*
352* Apply block Householder transformation from left.
353*
354 CALL pclarfb( 'Left', 'No transpose', 'Forward', 'Columnwise',
355 $ m, n, jb, work( ipv ), iv, jv, descv,
356 $ work( iptq ), a, ia, ja, desca, work( ipwk ) )
357*
358* Apply block Householder transformation from right.
359*
360 CALL pclarfb( 'Right', 'Conjugate transpose', 'Forward',
361 $ 'Rowwise', m, n-1, jb, work( ipw ), iv, jv+1,
362 $ descw, work( iptp ), a, ia, ja+1, desca,
363 $ work( ipwk ) )
364*
365 ELSE
366*
367 CALL descset( descd, ia+mn-1, 1, desca( mb_ ), 1,
368 $ desca( rsrc_ ), mycol, desca( ctxt_ ),
369 $ desca( lld_ ) )
370 CALL descset( desce, 1, ja+mn-2, 1, desca( nb_ ), myrow,
371 $ desca( csrc_ ), desca( ctxt_ ), 1 )
372*
373 DO 30 j = 0, mn-1
374 d1 = zero
375 e1 = zero
376 d2 = rzero
377 e2 = rzero
378 CALL pselget( ' ', ' ', d2, d, ia+j, 1, descd )
379 CALL pcelget( 'Rowwise', ' ', d1, a, ia+j, ja+j, desca )
380 IF( j.LT.(mn-1) ) THEN
381 CALL pselget( ' ', ' ', e2, e, 1, ja+j, desce )
382 CALL pcelget( 'Columnwise', ' ', e1, a, ia+j+1, ja+j,
383 $ desca )
384 END IF
385*
386 IF( ( abs( d1 - cmplx( d2 ) ).GT.( abs( d2 )*addbnd ) ) .OR.
387 $ ( abs( e1 - cmplx( e2 ) ).GT.( abs( e2 )*addbnd ) ) )
388 $ info = info + 1
389 30 CONTINUE
390*
391 DO 40 i = il, ia+nb-ioff, -nb
392 jb = min( ia+m-i, nb )
393 j = ja + i - ia
394 k = j - ja + 1
395*
396* Compute upper triangular matrix TQ from TAUQ.
397*
398 CALL pclarft( 'Forward', 'Columnwise', m-k, jb, a, i+1, j,
399 $ desca, tauq, work( iptq ), work( ipwk ) )
400*
401* Copy Householder vectors into workspace.
402*
403 CALL pclacpy( 'Lower', m-k, jb, a, i+1, j, desca,
404 $ work( ipv ), iv+1, jv, descv )
405 CALL pclaset( 'Upper', m-k, jb, zero, one, work( ipv ),
406 $ iv+1, jv, descv )
407*
408* Zero out the strict lower triangular part of A.
409*
410 CALL pclaset( 'Lower', m-k-1, jb, zero, zero, a, i+2, j,
411 $ desca )
412*
413* Compute upper triangular matrix TP from TAUP.
414*
415 CALL pclarft( 'Forward', 'Rowwise', n-k+1, jb, a, i, j,
416 $ desca, taup, work( iptp ), work( ipwk ) )
417*
418* Copy Householder vectors into workspace.
419*
420 CALL pclacpy( 'Upper', jb, n-k+1, a, i, j, desca,
421 $ work( ipw ), iv, jv, descw )
422 CALL pclaset( 'Lower', jb, n-k+1, zero, one, work( ipw ),
423 $ iv, jv, descw )
424*
425* Zero out the strict+1 upper triangular part of A.
426*
427 CALL pclaset( 'Upper', jb, n-k, zero, zero, a, i, j+1,
428 $ desca )
429*
430* Apply block Householder transformation from Left.
431*
432 CALL pclarfb( 'Left', 'No transpose', 'Forward',
433 $ 'Columnwise', m-k, n-k+1, jb, work( ipv ),
434 $ iv+1, jv, descv, work( iptq ), a, i+1, j,
435 $ desca, work( ipwk ) )
436*
437* Apply block Householder transformation from Right.
438*
439 CALL pclarfb( 'Right', 'Conjugate transpose', 'Forward',
440 $ 'Rowwise', m-k+1, n-k+1, jb, work( ipw ), iv,
441 $ jv, descw, work( iptp ), a, i, j, desca,
442 $ work( ipwk ) )
443*
444 descv( m_ ) = descv( m_ ) + nb
445 descv( rsrc_ ) = mod( descv( rsrc_ ) + nprow - 1, nprow )
446 descv( csrc_ ) = mod( descv( csrc_ ) + npcol - 1, npcol )
447 descw( n_ ) = descw( n_ ) + nb
448 descw( rsrc_ ) = descv( rsrc_ )
449 descw( csrc_ ) = descv( csrc_ )
450*
451 40 CONTINUE
452*
453* Handle first block separately
454*
455 jb = min( m, nb - ioff )
456 iv = ioff + 1
457 jv = ioff + 1
458*
459* Compute upper triangular matrix TQ from TAUQ.
460*
461 CALL pclarft( 'Forward', 'Columnwise', m-1, jb, a, ia+1, ja,
462 $ desca, tauq, work( iptq ), work( ipwk ) )
463*
464* Copy Householder vectors into workspace.
465*
466 CALL pclacpy( 'Lower', m-1, jb, a, ia+1, ja, desca,
467 $ work( ipv ), iv+1, jv, descv )
468 CALL pclaset( 'Upper', m-1, jb, zero, one, work( ipv ), iv+1,
469 $ jv, descv )
470*
471* Zero out the strict lower triangular part of A.
472*
473 CALL pclaset( 'Lower', m-2, jb, zero, zero, a, ia+2, ja,
474 $ desca )
475*
476* Compute upper triangular matrix TP from TAUP.
477*
478 CALL pclarft( 'Forward', 'Rowwise', n, jb, a, ia, ja, desca,
479 $ taup, work( iptp ), work( ipwk ) )
480*
481* Copy Householder vectors into workspace.
482*
483 CALL pclacpy( 'Upper', jb, n, a, ia, ja, desca, work( ipw ),
484 $ iv, jv, descw )
485 CALL pclaset( 'Lower', jb, n, zero, one, work( ipw ), iv, jv,
486 $ descw )
487*
488* Zero out the strict+1 upper triangular part of A.
489*
490 CALL pclaset( 'Upper', jb, n-1, zero, zero, a, ia, ja+1,
491 $ desca )
492*
493* Apply block Householder transformation from left
494*
495 CALL pclarfb( 'Left', 'No transpose', 'Forward', 'Columnwise',
496 $ m-1, n, jb, work( ipv ), iv+1, jv, descv,
497 $ work( iptq ), a, ia+1, ja, desca, work( ipwk ) )
498*
499* Apply block Householder transformation from right
500*
501 CALL pclarfb( 'Right', 'Conjugate transpose', 'Forward',
502 $ 'Rowwise', m, n, jb, work( ipw ), iv, jv, descw,
503 $ work( iptp ), a, ia, ja, desca, work( ipwk ) )
504 END IF
505*
506 CALL igsum2d( ictxt, 'All', ' ', 1, 1, info, 1, -1, 0 )
507*
508 RETURN
509*
510* End of PCGEBDRV
511*
512 END
float cmplx[2]
Definition pblas.h:136
subroutine descset(desc, m, n, mb, nb, irsrc, icsrc, ictxt, lld)
Definition descset.f:3
subroutine infog2l(grindx, gcindx, desc, nprow, npcol, myrow, mycol, lrindx, lcindx, rsrc, csrc)
Definition infog2l.f:3
subroutine pclaset(uplo, m, n, alpha, beta, a, ia, ja, desca)
Definition pcblastst.f:7508
subroutine pcelget(scope, top, alpha, a, ia, ja, desca)
Definition pcelget.f:2
subroutine pcgebdrv(m, n, a, ia, ja, desca, d, e, tauq, taup, work, info)
Definition pcgebdrv.f:3
#define max(A, B)
Definition pcgemr.c:180
#define min(A, B)
Definition pcgemr.c:181
subroutine pclacpy(uplo, m, n, a, ia, ja, desca, b, ib, jb, descb)
Definition pclacpy.f:3
subroutine pclarfb(side, trans, direct, storev, m, n, k, v, iv, jv, descv, t, c, ic, jc, descc, work)
Definition pclarfb.f:3
subroutine pclarft(direct, storev, n, k, v, iv, jv, descv, tau, t, work)
Definition pclarft.f:3
subroutine pselget(scope, top, alpha, a, ia, ja, desca)
Definition pselget.f:2