ScaLAPACK 2.1  2.1
ScaLAPACK: Scalable Linear Algebra PACKage
PB_CVMcontig.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__
20 void PB_CVMcontig( PB_VM_T * VM, int * NRPQ, int * NCPQ, int * IOFF,
21  int * JOFF )
22 #else
23 void PB_CVMcontig( VM, NRPQ, NCPQ, IOFF, JOFF )
24 /*
25 * .. Scalar Arguments ..
26 */
27  int * IOFF, * JOFF, * NCPQ, * NRPQ;
28  PB_VM_T * VM;
29 #endif
30 {
31 /*
32 * Purpose
33 * =======
34 *
35 * PB_CVMcontig computes the maximum number of contiguous rows and
36 * columns corresponding to the first diagonals of the local virtual
37 * matrix VM. This routine also returns the row and column offset of the
38 * first diagonal entry.
39 *
40 * Arguments
41 * =========
42 *
43 * VM (local input) pointer to a PB_VM_T structure
44 * On entry, VM is a pointer to a structure of type PB_VM_T,
45 * that contains the virtual matrix information (see pblas.h).
46 *
47 * NRPQ (local output) INTEGER
48 * On exit, NRPQ specifies the number of contiguous rows corres-
49 * ponding to the first diagonals of the local virtual matrix
50 * VM. On exit, NRPQ is at least zero.
51 *
52 * NCPQ (local output) INTEGER
53 * On exit, NCPQ specifies the number of contiguous columns cor-
54 * responding to the first diagonals of the local virtual matrix
55 * VM. On exit, NRPQ is at least zero.
56 *
57 * IOFF (local output) INTEGER
58 * On exit, IOFF is the local row offset of the first row cor-
59 * responding to a diagonal entry of the Virtual matrix VM. If
60 * no diagonals are found, the value zero is returned. On exit,
61 * IOFF is at least zero.
62 *
63 * JOFF (local output) INTEGER
64 * On exit, JOFF is the local column offset of the first column
65 * corresponding to a diagonal entry of the Virtual matrix VM.
66 * If no diagonals are found, the value zero is returned. On
67 * exit, JOFF is at least zero.
68 *
69 * -- Written on April 1, 1998 by
70 * Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
71 *
72 * ---------------------------------------------------------------------
73 */
74 /*
75 * .. Local Scalars ..
76 */
77  int ColCont=1, FirstD=0, GoSouth, GoEast, RowCont=1, ilow, imbloc,
78  inbloc, iupp, lcmt, lcmtnn=0, lcmt00, lmbloc, lnbloc, low, mb,
79  mblks, mbloc, mcur=0, mcurd, md=0, nb, nblks, nbloc, ncur=0,
80  ncurd, nd=0, npq=0, pmb, qnb, tmp1, tmp2, upp;
81 /* ..
82 * .. Executable Statements ..
83 *
84 */
85  *NRPQ = 0; *NCPQ = 0; *IOFF = 0; *JOFF = 0;
86  mblks = VM->mblks; nblks = VM->nblks;
87 /*
88 * Quick return if I don't own any blocks.
89 */
90  if( ( mblks == 0 ) || ( nblks == 0 ) ) return;
91 /*
92 * Retrieve the contents of VM structure fields
93 */
94  lcmt00 = VM->lcmt00;
95  imbloc = VM->imbloc; mb = VM->mb; lmbloc = VM->lmbloc;
96  iupp = VM->iupp; upp = VM->upp; pmb = VM->nprow * mb;
97  inbloc = VM->inbloc; nb = VM->nb; lnbloc = VM->lnbloc;
98  ilow = VM->ilow; low = VM->low; qnb = VM->npcol * nb;
99 /*
100 * Handle separately the first row and/or column of the LCM table. Update the
101 * LCM value of the curent block lcmt00, as well as the coordinates of the
102 * current entry in the LCM table (mcur,ncur).
103 */
104  GoSouth = ( lcmt00 > iupp );
105  GoEast = ( lcmt00 < ilow );
106 /*
107 * Go through the table looking for blocks owning diagonal entries.
108 */
109  if( !( GoSouth ) && !( GoEast ) )
110  {
111 /*
112 * The upper left block owns diagonal entries lcmt00 >= ilow && lcmt00 <= iupp
113 * Compute the number of diagonals in this block as well as lcm value (lcntnn)
114 * that its neighbor should have to preserve continuity.
115 */
116  if( lcmt00 >= 0 )
117  {
118  tmp2 = ( ( tmp1 = imbloc - lcmt00 ) > 0 ? tmp1 : 0 );
119  if( tmp2 < inbloc ) { npq = tmp2; lcmtnn = -npq; }
120  else if ( tmp2 == inbloc ) { npq = inbloc; lcmtnn = 0; }
121  else { npq = inbloc; lcmtnn = lcmt00 + npq; }
122  *IOFF += lcmt00;
123  }
124  else
125  {
126  tmp2 = ( ( tmp1 = inbloc + lcmt00 ) > 0 ? tmp1 : 0 );
127  if( tmp2 < imbloc ) { npq = tmp2; lcmtnn = npq; }
128  else if ( tmp2 == imbloc ) { npq = tmp2; lcmtnn = 0; }
129  else { npq = imbloc; lcmtnn = lcmt00 - npq; }
130  *JOFF -= lcmt00;
131  }
132 /*
133 * Save coordinates of last block owning diagonals. Set FirstD to one, since
134 * a block owning diagonals has been found.
135 */
136  md = 0; nd = 0; FirstD = 1;
137 /*
138 * Those rows and columns are obviously contiguous
139 */
140  *NRPQ = *NCPQ = npq;
141 /*
142 * Decide whether one should go south or east in the table: Go east if the
143 * block below the current one only owns lower entries. If this block, however,
144 * owns diagonals, then go south.
145 */
146  GoSouth = !( GoEast = ( lcmt00 - iupp + upp - pmb < ilow ) );
147  }
148 
149  if( GoSouth )
150  {
151 /*
152 * Go one step south in the LCM table. Adjust the current LCM value.
153 */
154  lcmt00 -= iupp - upp + pmb; mcur++;
155  if( !FirstD ) *IOFF += imbloc;
156 /*
157 * While there are blocks remaining that own upper entries, keep going south.
158 * Adjust the current LCM value accordingly.
159 */
160  while( ( mcur < mblks ) && ( lcmt00 > upp ) )
161  {
162  lcmt00 -= pmb;
163  mcur++;
164  if( !FirstD ) *IOFF += mb;
165  }
166 /*
167 * Return if no more row in the LCM table.
168 */
169  if( mcur >= mblks ) goto l_end;
170 /*
171 * lcmt00 <= upp. The current block owns either diagonals or lower entries.
172 * Save the current position in the LCM table. After this column has been
173 * completely taken care of, re-start from this row and the next column of
174 * the LCM table.
175 */
176  lcmt = lcmt00; mbloc = mb; mcurd = mcur;
177 
178  while( ( mcurd < mblks ) && ( lcmt >= ilow ) )
179  {
180  if( mcurd == mblks-1 ) mbloc = lmbloc;
181 /*
182 * A block owning diagonals lcmt00 >= ilow && lcmt00 <= upp has been found.
183 * If this is not the first one, update the booleans telling if the rows
184 * and/or columns are contiguous.
185 */
186  if( FirstD )
187  {
188  RowCont = RowCont &&
189  ( ( ( mcurd == md+1 ) && ( lcmtnn <= 0 ) && ( lcmt <= 0 ) ) ||
190  ( ( mcurd == md ) && ( ncur == nd+1 ) && ( lcmtnn == lcmt ) ) );
191  ColCont = ColCont &&
192  ( ( ( ncur == nd+1 ) && ( lcmtnn >= 0 ) && ( lcmt >= 0 ) ) ||
193  ( ( ncur == nd ) && ( mcurd == md+1 ) && ( lcmtnn == lcmt ) ) );
194  }
195 /*
196 * Compute the number of diagonals in this block as well as lcm value (lcntnn)
197 * that its neighbor should have to preserve continuity.
198 */
199  if( lcmt >= 0 )
200  {
201  tmp2 = ( ( tmp1 = mbloc - lcmt ) > 0 ? tmp1 : 0 );
202  if( tmp2 < inbloc ) { npq = tmp2; lcmtnn = -npq; }
203  else if ( tmp2 == inbloc ) { npq = inbloc; lcmtnn = 0; }
204  else { npq = inbloc; lcmtnn = lcmt + npq; }
205  if( !FirstD ) *IOFF += lcmt;
206  }
207  else
208  {
209  tmp2 = ( ( tmp1 = inbloc + lcmt ) > 0 ? tmp1 : 0 );
210  if( tmp2 < mbloc ) { npq = tmp2; lcmtnn = npq; }
211  else if ( tmp2 == mbloc ) { npq = tmp2; lcmtnn = 0; }
212  else { npq = mbloc; lcmtnn = lcmt - npq; }
213  if( !FirstD ) *JOFF -= lcmt;
214  }
215 /*
216 * Save coordinates of last block owning diagonals. Set FirstD to one, since
217 * a block owning diagonals has been found.
218 */
219  md = mcurd; nd = ncur; FirstD = 1;
220 /*
221 * If rows (resp columns) are still contiguous, add those npq rows (resp.
222 * columns).
223 */
224  if( RowCont ) *NRPQ += npq;
225  if( ColCont ) *NCPQ += npq;
226 /*
227 * Keep going south until there are no more blocks owning diagonals
228 */
229  lcmt00 = lcmt;
230  lcmt -= pmb;
231  mcur = mcurd++;
232  }
233 /*
234 * I am done with the first column of the LCM table. Go to the next column.
235 */
236  lcmt00 += low - ilow + qnb; ncur++;
237  if( !FirstD ) *JOFF += inbloc;
238  }
239  else if( GoEast )
240  {
241 /*
242 * Go one step east in the LCM table. Adjust the current LCM value.
243 */
244  lcmt00 += low - ilow + qnb; ncur++;
245  if( !FirstD ) *JOFF += inbloc;
246 /*
247 * While there are blocks remaining that own lower entries, keep going east
248 * in the LCM table. Adjust the current LCM value.
249 */
250  while( ( ncur < nblks ) && ( lcmt00 < low ) )
251  {
252  lcmt00 += qnb;
253  ncur++;
254  if( !FirstD ) *JOFF += nb;
255  }
256 /*
257 * Return if no more column in the LCM table.
258 */
259  if( ncur >= nblks ) goto l_end;
260 /*
261 * lcmt00 >= low. The current block owns either diagonals or upper entries. Save
262 * the current position in the LCM table. After this row has been completely
263 * taken care of, re-start from this column and the next row of the LCM table.
264 */
265  lcmt = lcmt00; nbloc = nb; ncurd = ncur;
266 
267  while( ( ncurd < nblks ) && ( lcmt <= iupp ) )
268  {
269  if( ncurd == nblks-1 ) nbloc = lnbloc;
270 /*
271 * A block owning diagonals lcmt00 >= low && lcmt00 <= iupp has been found.
272 * If this is not the first one, update the booleans telling if the rows
273 * and/or columns are contiguous.
274 */
275  if( FirstD )
276  {
277  RowCont = RowCont &&
278  ( ( ( mcur == md+1 ) && ( lcmtnn <= 0 ) && ( lcmt <= 0 ) ) ||
279  ( ( mcur == md ) && ( ncurd == nd+1 ) && ( lcmtnn == lcmt ) ) );
280  ColCont = ColCont &&
281  ( ( ( ncurd == nd+1 ) && ( lcmtnn >= 0 ) && ( lcmt >= 0 ) ) ||
282  ( ( ncurd == nd ) && ( mcur == md+1 ) && ( lcmtnn == lcmt ) ) );
283  }
284 /*
285 * Compute the number of diagonals in this block as well as lcm value (lcntnn)
286 * that its neighbor should have to preserve continuity.
287 */
288  if( lcmt >= 0 )
289  {
290  tmp2 = ( ( tmp1 = imbloc - lcmt ) > 0 ? tmp1 : 0 );
291  if( tmp2 < nbloc ) { npq = tmp2; lcmtnn = -npq; }
292  else if ( tmp2 == nbloc ) { npq = nbloc; lcmtnn = 0; }
293  else { npq = nbloc; lcmtnn = lcmt + npq; }
294  if( !FirstD ) *IOFF += lcmt;
295  }
296  else
297  {
298  tmp2 = ( ( tmp1 = nbloc + lcmt ) > 0 ? tmp1 : 0 );
299  if( tmp2 < imbloc ) { npq = tmp2; lcmtnn = npq; }
300  else if ( tmp2 == imbloc ) { npq = tmp2; lcmtnn = 0; }
301  else { npq = imbloc; lcmtnn = lcmt - npq; }
302  if( !FirstD ) *JOFF -= lcmt;
303  }
304 /*
305 * Save coordinates of last block owning diagonals. Set FirstD to one, since
306 * a block owning diagonals has been found.
307 */
308  md = mcur; nd = ncurd; FirstD = 1;
309 /*
310 * If rows (resp columns) are still contiguous, add those npq rows (resp.
311 * columns).
312 */
313  if( RowCont ) *NRPQ += npq;
314  if( ColCont ) *NCPQ += npq;
315 /*
316 * Keep going east until there are no more blocks owning diagonals.
317 */
318  lcmt00 = lcmt; lcmt += qnb; ncur = ncurd++;
319  }
320 /*
321 * I am done with the first row of the LCM table. Go to the next row.
322 */
323  lcmt00 -= iupp - upp + pmb; mcur++;
324  if( !FirstD ) *IOFF += imbloc;
325  }
326 /*
327 * Loop over the remaining columns of the LCM table.
328 */
329  nbloc = nb;
330 
331  while( ( RowCont || ColCont ) && ( ncur < nblks ) )
332  {
333  if( ncur == nblks-1 ) nbloc = lnbloc;
334 /*
335 * While there are blocks remaining that own upper entries, keep going south.
336 * Adjust the current LCM value accordingly.
337 */
338  while( ( mcur < mblks ) && ( lcmt00 > upp ) )
339  {
340  lcmt00 -= pmb;
341  mcur++;
342  if( !FirstD ) *IOFF += mb;
343  }
344 /*
345 * Return if no more row in the LCM table.
346 */
347  if( mcur >= mblks ) goto l_end;
348 /*
349 * lcmt00 <= upp. The current block owns either diagonals or lower entries.
350 * Save the current position in the LCM table. After this column has been
351 * completely taken care of, re-start from this row and the next column of
352 * the LCM table.
353 */
354  lcmt = lcmt00; mbloc = mb; mcurd = mcur;
355 
356  while( ( mcurd < mblks ) && ( lcmt >= low ) )
357  {
358  if( mcurd == mblks-1 ) mbloc = lmbloc;
359 /*
360 * A block owning diagonals lcmt00 >= low && lcmt00 <= upp has been found.
361 * If this is not the first one, update the booleans telling if the rows
362 * and/or columns are contiguous.
363 */
364  if( FirstD )
365  {
366  RowCont = RowCont &&
367  ( ( ( mcurd == md+1 ) && ( lcmtnn <= 0 ) && ( lcmt <= 0 ) ) ||
368  ( ( mcurd == md ) && ( ncur == nd+1 ) && ( lcmtnn == lcmt ) ) );
369  ColCont = ColCont &&
370  ( ( ( ncur == nd+1 ) && ( lcmtnn >= 0 ) && ( lcmt >= 0 ) ) ||
371  ( ( ncur == nd ) && ( mcurd == md+1 ) && ( lcmtnn == lcmt ) ) );
372  }
373 /*
374 * Compute the number of diagonals in this block as well as lcm value (lcntnn)
375 * that its neighbor should have to preserve continuity.
376 */
377  if( lcmt >= 0 )
378  {
379  tmp2 = ( ( tmp1 = mbloc - lcmt ) > 0 ? tmp1 : 0 );
380  if( tmp2 < nbloc ) { npq = tmp2; lcmtnn = -npq; }
381  else if ( tmp2 == nbloc ) { npq = nbloc; lcmtnn = 0; }
382  else { npq = nbloc; lcmtnn = lcmt + npq; }
383  if( !FirstD ) *IOFF += lcmt;
384  }
385  else
386  {
387  tmp2 = ( ( tmp1 = nbloc + lcmt ) > 0 ? tmp1 : 0 );
388  if( tmp2 < mbloc ) { npq = tmp2; lcmtnn = npq; }
389  else if ( tmp2 == mbloc ) { npq = tmp2; lcmtnn = 0; }
390  else { npq = mbloc; lcmtnn = lcmt - npq; }
391  if( !FirstD ) *JOFF -= lcmt;
392  }
393 /*
394 * Save coordinates of last block owning diagonals. Set FirstD to one, since
395 * a block owning diagonals has been found.
396 */
397  md = mcurd; nd = ncur; FirstD = 1;
398 /*
399 * If rows (resp columns) are still contiguous, add those npq rows (resp.
400 * columns).
401 */
402  if( RowCont ) *NRPQ += npq;
403  if( ColCont ) *NCPQ += npq;
404 /*
405 * Keep going south until there are no more blocks owning diagonals
406 */
407  lcmt00 = lcmt;
408  lcmt -= pmb;
409  mcur = mcurd++;
410  }
411 /*
412 * I am done with this column of the LCM table. Go to the next column until
413 * there are no more column in the table.
414 */
415  lcmt00 += qnb; ncur++;
416  if( !FirstD ) *JOFF += nb;
417  }
418 
419 l_end:
420 /*
421 * If no diagonals were found, reset IOFF and JOFF to zero.
422 */
423  if( !FirstD ) { *IOFF = 0; *JOFF = 0; }
424 /*
425 * End of PB_CVMcontig
426 */
427 }
PB_VM_T::lcmt00
int lcmt00
Definition: pblas.h:435
PB_VM_T::inbloc
int inbloc
Definition: pblas.h:450
PB_VM_T::iupp
int iupp
Definition: pblas.h:443
PB_VM_T::imbloc
int imbloc
Definition: pblas.h:439
PB_VM_T::low
int low
Definition: pblas.h:455
PB_VM_T::npcol
int npcol
Definition: pblas.h:457
PB_CVMcontig
void PB_CVMcontig(PB_VM_T *VM, int *NRPQ, int *NCPQ, int *IOFF, int *JOFF)
Definition: PB_CVMcontig.c:23
PB_VM_T::mblks
int mblks
Definition: pblas.h:442
PB_VM_T::lmbloc
int lmbloc
Definition: pblas.h:441
PB_VM_T::upp
int upp
Definition: pblas.h:444
PB_VM_T::nprow
int nprow
Definition: pblas.h:446
PB_VM_T::nblks
int nblks
Definition: pblas.h:453
PB_VM_T
Definition: pblas.h:432
PB_VM_T::lnbloc
int lnbloc
Definition: pblas.h:452
PB_VM_T::ilow
int ilow
Definition: pblas.h:454
PB_VM_T::mb
int mb
Definition: pblas.h:440
PB_VM_T::nb
int nb
Definition: pblas.h:451