SCALAPACK 2.2.2
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
PB_CVMnpq.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_CVMnpq( PB_VM_T * VM )
21#else
23/*
24* .. Array Arguments ..
25*/
26 PB_VM_T * VM;
27#endif
28{
29/*
30* Purpose
31* =======
32*
33* PB_CVMnpq computes the number of diagonal entries in the virtual ma-
34* specified by VM.
35*
36* Arguments
37* =========
38*
39* VM (local input) pointer to a PB_VM_T structure
40* On entry, VM is a pointer to a structure of type PB_VM_T,
41* that contains the virtual matrix information (see pblas.h).
42*
43* -- Written on April 1, 1998 by
44* Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
45*
46* ---------------------------------------------------------------------
47*/
48/*
49* .. Local Scalars ..
50*/
51 Int GoEast, GoSouth, Pmb, Qnb, gcdb, ilow, imbloc, inbloc, iupp,
52 kmax, kmin, k1, k2, k3, lcmb, lcmp, lcmq, lcmt, lcmt00,
53 lmbloc, lnbloc, low, l1, l2, l3, m, mb, mblkd, mblks, mbloc,
54 n, nb, nblkd, nblks, nbloc, nlcmblks, npcol, npq=0, nprow,
55 tmp1, tmp2, upp;
56/* ..
57* .. Executable Statements ..
58*
59*/
60 m = VM->mp; n = VM->nq;
61/*
62* Quick return if I don't own any data.
63*/
64 if( ( m == 0 ) || ( n == 0 ) ) return( 0 );
65/*
66* The only valuable shortcut is when the virtual grid and the blocks are
67* square, and the offset is zero or the grid is 1x1.
68*/
69 mb = VM->mb; nprow = VM->nprow;
70 nb = VM->nb; npcol = VM->npcol;
71
72 if( ( ( VM->offd == 0 ) && ( VM->imb1 == VM->inb1 ) && ( mb == nb ) &&
73 ( nprow == npcol ) ) || ( ( nprow == 1 ) && ( npcol == 1 ) ) )
74 {
75 if( VM->prow == VM->pcol ) return( MIN( m, n ) );
76 else return( 0 );
77 }
78/*
79* Retrieve the contents of VM structure fields
80*/
81 lcmt00 = VM->lcmt00;
82 mblks = VM->mblks; imbloc = VM->imbloc; lmbloc = VM->lmbloc;
83 iupp = VM->iupp; upp = VM->upp;
84 nblks = VM->nblks; inbloc = VM->inbloc; lnbloc = VM->lnbloc;
85 ilow = VM->ilow; low = VM->low;
86 lcmb = VM->lcmb;
87 Pmb = nprow * mb;
88 Qnb = npcol * nb;
89/*
90* Handle separately the first row and/or column of the LCM table. Update the
91* LCM value of the curent block lcmt00, as well as the number of rows and
92* columns mblks and nblks remaining in the LCM table.
93*/
94 GoSouth = ( lcmt00 > iupp );
95 GoEast = ( lcmt00 < ilow );
96/*
97* Go through the table looking for blocks owning diagonal entries.
98*/
99 if( !( GoSouth ) && !( GoEast ) )
100 {
101/*
102* The upper left block owns diagonal entries lcmt00 >= ilow && lcmt00 <= iupp
103*/
104 npq += ( lcmt00 >= 0 ?
105 ( ( tmp2 = ( tmp1 = imbloc - lcmt00 ) > 0 ? tmp1 : 0 ) < inbloc ?
106 tmp2 : inbloc ) :
107 ( ( tmp2 = ( tmp1 = inbloc + lcmt00 ) > 0 ? tmp1 : 0 ) > imbloc ?
108 imbloc : tmp2 ) );
109/*
110* Decide whether one should go south or east in the table: Go east if
111* the block below the current one only owns lower entries. If this block,
112* however, owns diagonals, then go south.
113*/
114 GoSouth = !( GoEast = ( ( lcmt00 - ( iupp - upp + Pmb ) ) < ilow ) );
115 }
116
117 if( GoSouth )
118 {
119/*
120* Go one step south in the LCM table. Adjust the current LCM value.
121*/
122 lcmt00 -= iupp - upp + Pmb; mblks--;
123/*
124* While there are blocks remaining that own upper entries, keep going south.
125* Adjust the current LCM value accordingly.
126*/
127 while( mblks && ( lcmt00 > upp ) ) { lcmt00 -= Pmb; mblks--; }
128/*
129* Return if no more row in the LCM table.
130*/
131 if( mblks <= 0 ) return( npq );
132/*
133* lcmt00 <= upp. The current block owns either diagonals or lower entries.
134* Save the current position in the LCM table. After this column has been
135* completely taken care of, re-start from this row and the next column of
136* the LCM table.
137*/
138 lcmt = lcmt00; mblkd = mblks; mbloc = mb;
139
140 while( mblkd && ( lcmt >= ilow ) )
141 {
142/*
143* A block owning diagonals lcmt00 >= ilow && lcmt00 <= upp has been found.
144*/
145 if( mblkd == 1 ) mbloc = lmbloc;
146 npq += ( lcmt >= 0 ?
147 ( ( tmp2 = ( tmp1 = mbloc - lcmt ) > 0 ? tmp1 : 0 ) < inbloc ?
148 tmp2 : inbloc ) :
149 ( ( tmp2 = ( tmp1 = inbloc + lcmt ) > 0 ? tmp1 : 0 ) > mbloc ?
150 mbloc : tmp2 ) );
151/*
152* Keep going south until there are no more blocks owning diagonals
153*/
154 lcmt00 = lcmt; lcmt -= Pmb; mblks = mblkd--;
155 }
156/*
157* I am done with the first column of the LCM table. Go to the next column.
158*/
159 lcmt00 += low - ilow + Qnb; nblks--;
160 }
161 else if( GoEast )
162 {
163/*
164* Go one step east in the LCM table. Adjust the current LCM value.
165*/
166 lcmt00 += low - ilow + Qnb; nblks--;
167/*
168* While there are blocks remaining that own lower entries, keep going east
169* in the LCM table. Adjust the current LCM value accordingly.
170*/
171 while( nblks && ( lcmt00 < low ) ) { lcmt00 += Qnb; nblks--; }
172/*
173* Return if no more column in the LCM table.
174*/
175 if( nblks <= 0 ) return( npq );
176/*
177* lcmt00 >= low. The current block owns either diagonals or upper entries. Save
178* the current position in the LCM table. After this row has been completely
179* taken care of, re-start from this column and the next row of the LCM table.
180*/
181 lcmt = lcmt00; nblkd = nblks; nbloc = nb;
182
183 while( nblkd && ( lcmt <= iupp ) )
184 {
185/*
186* A block owning diagonals lcmt00 >= low && lcmt00 <= iupp has been found.
187*/
188 if( nblkd == 1 ) nbloc = lnbloc;
189 npq += ( lcmt >= 0 ?
190 ( ( tmp2 = ( tmp1 = imbloc - lcmt ) > 0 ? tmp1 : 0 ) < nbloc ?
191 tmp2 : nbloc ) :
192 ( ( tmp2 = ( tmp1 = nbloc + lcmt ) > 0 ? tmp1 : 0 ) > imbloc ?
193 imbloc : tmp2 ) );
194/*
195* Keep going east until there are no more blocks owning diagonals.
196*/
197 lcmt00 = lcmt; lcmt += Qnb; nblks = nblkd--;
198 }
199/*
200* I am done with the first row of the LCM table. Go to the next row.
201*/
202 lcmt00 -= iupp - upp + Pmb; mblks--;
203 }
204/*
205* If the current block does not have diagonal elements, find the closest one in
206* the LCM table having some.
207*/
208 if( lcmt00 < low || lcmt00 > upp )
209 {
210 while( mblks && nblks )
211 {
212 while( mblks && ( lcmt00 > upp ) ) { lcmt00 -= Pmb; mblks--; }
213 if( lcmt00 >= low ) break;
214 while( nblks && ( lcmt00 < low ) ) { lcmt00 += Qnb; nblks--; }
215 if( lcmt00 <= upp ) break;
216 }
217 }
218 if( !( mblks ) || !( nblks ) ) return( npq );
219/*
220* Figure out how many "full" lcm blocks are remaining.
221*/
222 gcdb = ( Pmb * Qnb ) / lcmb;
223
224 if( lcmt00 > 0 )
225 {
226 kmin = - ( lcmb / gcdb );
227 kmax = ( lcmb - Qnb ) / gcdb;
228 tmp1 = ( mblks - 1 ) / ( lcmp = lcmb / Pmb );
229 tmp2 = nblks / ( lcmq = lcmb / Qnb );
230 }
231 else if( lcmt00 < 0 )
232 {
233 kmin = - ( ( lcmb - Pmb ) / gcdb );
234 kmax = lcmb / gcdb;
235 tmp1 = mblks / ( lcmp = lcmb / Pmb );
236 tmp2 = ( nblks - 1 ) / ( lcmq = lcmb / Qnb );
237 }
238 else
239 {
240 kmin = - ( ( lcmb - Pmb ) / gcdb );
241 kmax = ( lcmb - Qnb ) / gcdb;
242 tmp1 = mblks / ( lcmp = lcmb / Pmb );
243 tmp2 = nblks / ( lcmq = lcmb / Qnb );
244 }
245/*
246* The last block, even if it is an lcm block will be handled separately
247*/
248 nlcmblks = MIN( tmp1, tmp2 );
249 if( nlcmblks ) nlcmblks--;
250/*
251* Compute the lcm block part, update mblks and nblks
252*/
253 if( nlcmblks )
254 {
255 tmp2 = 0;
256
257 k1 = -lcmt00; k1 = ICEIL( k1, gcdb ); l1 = k1 - 1;
258 l1 = MIN( l1, kmax ); k1 = MAX( k1, kmin );
259
260 k3 = upp - lcmt00; k3 = FLOOR( k3, gcdb ); k3 = MIN( k3, kmax );
261 l3 = low - lcmt00; l3 = ICEIL( l3, gcdb ); l3 = MAX( l3, kmin );
262
263 if( k1 <= k3 )
264 {
265 k2 = mb - nb - lcmt00;
266 k2 = ICEIL( k2, gcdb );
267
268 if( k2 < k1 )
269 {
270/*
271* k2 < k1
272*/
273 tmp1 = k3 - k1 + 1;
274 tmp2 = tmp1 * ( mb - lcmt00 );
275 tmp1 *= ( k3 + k1 )*gcdb;
276 tmp2 += ( tmp1 > 0 ? -( tmp1 / 2 ) : (-tmp1) / 2 );
277 }
278 else if( k2 > k3 )
279 {
280/*
281* k2 = k3 + 1
282*/
283 tmp2 = ( k3 - k1 + 1 ) * nb;
284 }
285 else
286 {
287/*
288* k1 <= k2 <= k3
289*/
290 tmp1 = k3 - k2 + 1;
291 tmp2 = ( k2 - k1 ) * nb + tmp1 * ( mb - lcmt00 );
292 tmp1 *= ( k3 + k2 ) * gcdb;
293 tmp2 += ( tmp1 > 0 ? -( tmp1 / 2 ) : (-tmp1) / 2 );
294 }
295 }
296
297 if( l3 <= l1 )
298 {
299 l2 = mb - nb - lcmt00;
300 l2 = FLOOR( l2, gcdb );
301
302 if( l2 > l1 )
303 {
304/*
305* l2 > l1
306*/
307 tmp1 = l1 - l3 + 1;
308 tmp2 += tmp1 * ( nb + lcmt00 );
309 tmp1 *= ( l3 + l1 ) * gcdb;
310 tmp2 += ( tmp1 > 0 ? ( tmp1 / 2 ) : -( (-tmp1) / 2 ) );
311 }
312 else if( l2 < l3 )
313 {
314/*
315* l2 = l3 - 1
316*/
317 tmp2 += ( l1 - l3 + 1 ) * mb;
318 }
319 else
320 {
321/*
322* l3 <= l2 <= l1
323*/
324 tmp1 = l2 - l3 + 1;
325 tmp2 += ( l1 - l2 ) * mb + tmp1 * ( nb + lcmt00 );
326 tmp1 *= ( l3 + l2 ) * gcdb;
327 tmp2 += ( tmp1 > 0 ? ( tmp1 / 2 ) : -( (-tmp1) / 2 ) );
328 }
329 }
330 npq += nlcmblks * tmp2;
331
332 mblks -= nlcmblks * lcmp;
333 nblks -= nlcmblks * lcmq;
334 }
335/*
336* Handle last partial (lcm) block separately
337*/
338 nbloc = nb;
339 while( nblks )
340 {
341/*
342* The current block owns diagonals. Save the current position in the LCM table.
343* After this column has been completely taken care of, re-start from this row
344* and the next column in the LCM table.
345*/
346 if( nblks == 1 ) nbloc = lnbloc;
347 while( mblks && lcmt00 > upp ) { lcmt00 -= Pmb; mblks--; }
348
349 if( mblks <= 0 ) return( npq );
350
351 lcmt = lcmt00; mblkd = mblks; mbloc = mb;
352
353 while( mblkd && ( lcmt >= low ) )
354 {
355/*
356* A block owning diagonals lcmt00 >= low && lcmt00 <= upp has been found.
357*/
358 if( mblkd == 1 ) mbloc = lmbloc;
359 npq += ( lcmt >= 0 ?
360 ( ( tmp2 = ( tmp1 = mbloc - lcmt ) > 0 ? tmp1 : 0 ) < nbloc ?
361 tmp2 : nbloc ) :
362 ( ( tmp2 = ( tmp1 = nbloc + lcmt ) > 0 ? tmp1 : 0 ) > mbloc ?
363 mbloc : tmp2 ) );
364/*
365* Keep going south until there are no more blocks owning diagonals
366*/
367 lcmt00 = lcmt; lcmt -= Pmb; mblks = mblkd--;
368 }
369/*
370* I am done with this column of the LCM table. Go to the next column ...
371*/
372 lcmt00 += Qnb; nblks--;
373/*
374* ... until there are no more columns.
375*/
376 }
377/*
378* Return the number of diagonals found.
379*/
380 return( npq );
381/*
382* End of PB_CVMnpq
383*/
384}
#define Int
Definition Bconfig.h:22
#define MAX(a_, b_)
Definition PBtools.h:77
#define MIN(a_, b_)
Definition PBtools.h:76
#define ICEIL(a, b)
Definition PBtools.h:81
Int PB_CVMnpq()
#define FLOOR(a, b)
Definition PBtools.h:79
Int lcmb
Definition pblas.h:463
Int lnbloc
Definition pblas.h:456
Int low
Definition pblas.h:459
Int iupp
Definition pblas.h:447
Int npcol
Definition pblas.h:461
Int nprow
Definition pblas.h:450
Int lcmt00
Definition pblas.h:439
Int pcol
Definition pblas.h:460
Int inbloc
Definition pblas.h:454
Int ilow
Definition pblas.h:458
Int offd
Definition pblas.h:438
Int inb1
Definition pblas.h:453
Int nblks
Definition pblas.h:457
Int mp
Definition pblas.h:441
Int prow
Definition pblas.h:449
Int imbloc
Definition pblas.h:443
Int nq
Definition pblas.h:452
Int lmbloc
Definition pblas.h:445
Int nb
Definition pblas.h:455
Int imb1
Definition pblas.h:442
Int mblks
Definition pblas.h:446
Int mb
Definition pblas.h:444
Int upp
Definition pblas.h:448