SCALAPACK 2.2.2
LAPACK: Linear Algebra PACKage
All Classes Files Functions Variables Typedefs Macros
PB_Cnnxtroc.c
Go to the documentation of this file.
1/* ---------------------------------------------------------------------
2*
3* -- PBLAS auxiliary routine (version 2.0) --
4* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
5* and University of California, Berkeley.
6* April 1, 1998
7*
8* ---------------------------------------------------------------------
9*/
10/*
11* Include files
12*/
13#include "../pblas.h"
14#include "../PBpblas.h"
15#include "../PBtools.h"
16#include "../PBblacs.h"
17#include "../PBblas.h"
18
19#ifdef __STDC__
20Int PB_Cnnxtroc( Int N, Int I, Int INB, Int NB, Int PROC, Int SRCPROC,
21 Int NPROCS )
22#else
23Int PB_Cnnxtroc( N, I, INB, NB, PROC, SRCPROC, NPROCS )
24/*
25* .. Scalar Arguments ..
26*/
27 Int I, INB, N, NB, NPROCS, PROC, SRCPROC;
28#endif
29{
30/*
31* Purpose
32* =======
33*
34* PB_Cnnxtroc computes the number of next rows or columns of a subma-
35* trix that are possessed by processes closer to SRCPROC1 than PROC
36* where SRCPROC1 is the process owning the row or column globally in-
37* dexed by I. The submatrix is defined by giving out N rows or columns
38* starting from global index I. Therefore, if SRCPROC=0 and PROC=1,
39* then PB_Cnnxtroc returns the number of matrix rows or columns owned
40* by processes 2, 3 ... NPROCS-1.
41*
42* In fact, if the same exact parameters N, I, INB, NB, SRCPROC and
43* NPROCS are passed to PB_Cnpreroc, PB_Cnumroc and PB_Cnnxtroc produ-
44* cing respectively npre, np and nnxt, then npre + np + nnxt = N in
45* every process PROC.
46*
47* Arguments
48* =========
49*
50* N (global input) INTEGER
51* On entry, N specifies the number of rows/columns being dealt
52* out. N must be at least zero.
53*
54* I (global input) INTEGER
55* On entry, I specifies the global index of the matrix entry.
56* I must be at least zero.
57*
58* INB (global input) INTEGER
59* On entry, INB specifies the size of the first block of the
60* global matrix distribution. INB must be at least one.
61*
62* NB (global input) INTEGER
63* On entry, NB specifies the size of the blocks used to parti-
64* tion the matrix. NB must be at least one.
65*
66* PROC (local input) INTEGER
67* On entry, PROC specifies the coordinate of the process whose
68* local portion is determined. PROC must be at least zero and
69* strictly less than NPROCS.
70*
71* SRCPROC (global input) INTEGER
72* On entry, SRCPROC specifies the coordinate of the process
73* that possesses the first row or column of the matrix. When
74* SRCPROC = -1, the data is not distributed but replicated,
75* otherwise SRCPROC must be at least zero and strictly less
76* than NPROCS.
77*
78* NPROCS (global input) INTEGER
79* On entry, NPROCS specifies the total number of process rows
80* or columns over which the matrix is distributed. NPROCS must
81* be at least one.
82*
83* -- Written on April 1, 1998 by
84* Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
85*
86* ---------------------------------------------------------------------
87*/
88/*
89* .. Local Scalars ..
90*/
91 Int ilocblk, mydist, nblocks;
92/* ..
93* .. Executable Statements ..
94*
95*/
96 if( ( SRCPROC == -1 ) || ( NPROCS == 1 ) )
97/*
98* The data is not distributed, or there is just one process in this dimension
99* of the grid.
100*/
101 return( 0 );
102/*
103* Compute coordinate of process owning I and corresponding INB
104*/
105 if( ( INB -= I ) <= 0 )
106 {
107/*
108* I is not in first block, find out which process has it and update size of
109* first block
110*/
111 nblocks = ( -INB ) / NB + 1;
112 SRCPROC += nblocks;
113 SRCPROC -= ( SRCPROC / NPROCS ) * NPROCS;
114 INB += nblocks * NB;
115 }
116/*
117* Now everything is just like N, I=0, INB, NB, SRCPROC, NPROCS. If the source
118* process owns the N rows or columns, nothing follows me ...
119*/
120 if( N <= INB ) return( 0 );
121/*
122* The discussion goes as follows: compute my distance from the source process
123* so that within this process coordinate system, the source process is the
124* process such that mydist = 0, or equivalently PROC == SRCPROC.
125*
126* Find out how many full blocks are globally (nblocks) and locally (ilocblk)
127* in those N entries. Then remark that
128*
129* when mydist < nblocks - ilocblk * NPROCS, I own ilocblk + 1 full blocks,
130* when mydist > nblocks - ilocblk * NPROCS, I own ilocblk full blocks,
131* when mydist = nblocks - ilocblk * NPROCS, either the last block is not full
132* and I own it, or the last block is full and I am the first process owning
133* only ilocblk full blocks.
134*/
135 nblocks = ( N - INB ) / NB + 1;
136
137 if( PROC == SRCPROC )
138 {
139/*
140* First note that I cannot be the source and the last process because mydist=0
141* and NPROCS > 1. Since mydist = 0 and nblocks - ilocblk * NPROCS >= 0, there
142* are only two possible cases:
143*
144* 1) When mydist = nblocks - ilocblk * NPROCS = 0, that is NPROCS divides
145* the global number of full blocks, then the source process SRCPROC owns
146* one more block than the other processes; Thus, N can be rewritten as
147* N = INB + (nblocks-1) * NB + LNB with LNB >= 0 size of the last block.
148* Similarly, the local value Np corresponding to the local number of rows
149* and columns owned by the source process is INB + (ilocblk-1)*NB + LNB,
150* that is N + ( ilocblk-1 - (nblocks-1) )*NB. Therefore, there must be
151* ( nblocks - ilocblk ) * NB rows or columns following me. Note that this
152* case cannot happen when ilocblk is zero, since nblocks is at least one.
153*
154* 2) mydist = 0 < nblocks - ilocblk * NPROCS, the source process only owns
155* full blocks, and therefore locally INB + ilocblk * NB rows or columns.
156* Thus, N - INB - ilocblk * NB rows or columns follow me. Note that when
157* ilocblk is zero, this becomes simply N - INB.
158*/
159 if( nblocks < NPROCS ) return( N - INB );
160
161 ilocblk = nblocks / NPROCS;
162 return( ( ( nblocks - ilocblk * NPROCS ) ? N - INB - ilocblk * NB :
163 ( nblocks - ilocblk ) * NB ) );
164 }
165 else
166 {
167/*
168* I am not the source process. Compute my distance from the source process.
169*/
170 if( ( mydist = PROC - SRCPROC ) < 0 ) mydist += NPROCS;
171/*
172* If I am the last process i.e. mydist = NPROCS - 1, nothing follows me.
173*/
174 if( mydist == NPROCS - 1 ) return( 0 );
175/*
176* Otherwise, when mydist >= nblocks - ilocblk * NPROCS, there are exactly
177* NB * ilocblk * ( NPROCS - mydist ) rows or columns after me including mine,
178* i.e NB * ilocblk * ( NPROCS - 1 - mydist ) rows or columns following me.
179* Finally, when 0 < mydist < nblocks - ilocblk * NPROCS, the number of rows
180* or columns preceeding me is INB + ilocblk * NB + mydist*( ilocblk+1 )*NB
181* including mine, therefore there are N-INB-NB*( ilocblk+mydist*(ilocblk+1) )
182* rows or columns following me.
183*/
184 if( nblocks < NPROCS )
185 return( ( ( mydist < nblocks ) ? N - mydist * NB - INB : 0 ) );
186
187 ilocblk = nblocks / NPROCS;
188 return( ( ( mydist >= ( nblocks - ilocblk * NPROCS ) ) ?
189 ( NPROCS - 1 - mydist ) * ilocblk * NB :
190 N - INB - ( ilocblk * mydist + ilocblk + mydist )*NB ) );
191 }
192/*
193* End of PB_Cnnxtroc
194*/
195}
#define Int
Definition Bconfig.h:22
Int PB_Cnnxtroc()