File: PB_Cg2lrem.c

package info (click to toggle)
scalapack 1.7-5
  • links: PTS
  • area: main
  • in suites: woody
  • size: 33,956 kB
  • ctags: 30,434
  • sloc: fortran: 309,685; ansic: 64,027; makefile: 1,836; sh: 4
file content (182 lines) | stat: -rw-r--r-- 6,456 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
/* ---------------------------------------------------------------------
*
*  -- PBLAS auxiliary routine (version 2.0) --
*     University of Tennessee, Knoxville, Oak Ridge National Laboratory,
*     and University of California, Berkeley.
*     April 1, 1998
*
*  ---------------------------------------------------------------------
*/
/*
*  Include files
*/
#include "../pblas.h"
#include "../PBpblas.h"
#include "../PBtools.h"
#include "../PBblacs.h"
#include "../PBblas.h"

#ifdef __STDC__
int PB_Cg2lrem( int IG, int INB, int NB, int MYPROC, int SRCPROC, int NPROCS )
#else
int PB_Cg2lrem( IG, INB, NB, MYPROC, SRCPROC, NPROCS )
/*
*  .. Scalar Arguments ..
*/
   int            IG, INB, NB, NPROCS, MYPROC, SRCPROC;
#endif
{
/*
*  Purpose
*  =======
*
*  PB_Cg2lrem computes the local index of a matrix entry pointed  to  by
*  the global index IG. Note that when MYPROC is not the process  owning
*  this entry, this routine  returns the closest larger local index cor-
*  responding to IG just like the routine PB_Cinfog2l.
*
*  Arguments
*  =========
*
*  IG      (global input) INTEGER
*          On entry, IG specifies the global index of the matrix  entry.
*          IG must be at least zero.
*
*  INB     (global input) INTEGER
*          On entry,  INB  specifies  the size of the first block of the
*          global matrix. INB must be at least one.
*
*  NB      (global input) INTEGER
*          On entry, NB specifies the size of the blocks used to  parti-
*          tion the matrix. NB must be at least one.
*
*  MYPROC  (global input) INTEGER
*          On entry,  MYPROC  specifies  the process number in which the
*          value of the local index is to be computed. MYPROC must be at
*          least zero and strictly less than NPROCS.
*
*  SRCPROC (global input) INTEGER
*          On entry, if SRCPROC = -1, the data  is not  distributed  but
*          replicated,  in  which  case  this  routine returns IG in all
*          processes. Otherwise, the value of SRCPROC is ignored.
*
*  NPROCS  (global input) INTEGER
*          On entry,  NPROCS  specifies the total number of process rows
*          or columns over which the matrix is distributed.  NPROCS must
*          be at least one.
*
*  -- Written on April 1, 1998 by
*     Antoine Petitet, University of Tennessee, Knoxville 37996, USA.
*
*  ---------------------------------------------------------------------
*/
/*
*  .. Local Scalars ..
*/
   int            ilocblk, mydist, nblocks, proc;
/* ..
*  .. Executable Statements ..
*
*/
/*
*  The data is not distributed, or there is just one process in this dimension
*  of the grid.
*/
   if( ( SRCPROC == -1 ) || ( NPROCS == 1 ) ) return( IG );
/*
*  IG refers to an entry in the first block
*/
   if( IG < INB ) return( ( MYPROC == SRCPROC ? IG : 0 ) );
/*
*  The discussion goes as follows: compute my distance from the source process
*  so that within this process coordinate system, the source process is the
*  process such that mydist = 0, or equivalently MYROC == SRCPROC.
*
*  Find out the global coordinate of the block IG belongs to (nblocks), as well
*  as the minimum local number of blocks that every process has.
*
*  when mydist < nblocks - ilocblk * NPROCS, I own ilocblk + 1 full blocks,
*  when mydist > nblocks - ilocblk * NPROCS, I own ilocblk     full blocks,
*  when mydist = nblocks - ilocblk * NPROCS, I own ilocblk     full blocks
*  but not IG, or I own ilocblk + 1 blocks and the entry IG refers to.
*/
   if( MYPROC == SRCPROC )
   {
/*
*  If I am the source process and there are less than NPROCS blocks, then
*  the local index in that process is INB.
*/
      nblocks = ( IG - INB ) / NB + 1;
      if( nblocks < NPROCS ) return( INB );
/*
*  IG refers to an entry that is not in the first block, find out which process
*  has it.
*/
      proc    = SRCPROC + nblocks;
      proc   -= ( proc / NPROCS ) * NPROCS;
/*
*  Since mydist = 0 and nblocks - ilocblk * NPROCS >= 0, there are only three
*  possible cases:
*
*    1) When 0 = mydist = nblocks - ilocblk * NPROCS = 0 and I don't own IG, in
*       which case II = INB + ( ilocblk - 1 ) * NB. Note that this case cannot
*       happen when ilocblk is zero, since nblocks is at least one.
*
*    2) When 0 = mydist = nblocks - ilocblk * NPROCS = 0 and I own IG, in which
*       case IG and II can respectively be written as INB + (nblocks-1)*NB + IL,
*       INB + (ilocblk-1) * NB + IL. That is II = IG + ( ilocblk - nblocks )*NB.
*       Note that this case cannot happen when ilocblk is zero, since nblocks
*       is at least one.
*
*    3) mydist = 0 < nblocks - ilocblk * NPROCS, the source process owns
*       ilocblk+1 full blocks, and therefore II = INB + ilocblk * NB. Note
*       that when ilocblk is zero, II is just INB.
*/
      ilocblk = nblocks / NPROCS;
      if( ilocblk * NPROCS >= nblocks )
         return( ( ( MYPROC == proc ) ? IG + ( ilocblk - nblocks ) * NB :
                   INB + ( ilocblk - 1 ) * NB ) );
      else
         return( INB + ilocblk * NB );
   }
   else
   {
/*
*  IG refers to an entry that is not in the first block, find out which process
*  has it.
*/
      nblocks = ( IG -= INB ) / NB + 1;
      proc    = SRCPROC + nblocks;
      proc   -= ( proc / NPROCS ) * NPROCS;
/*
*  Compute my distance from the source process so that within this process
*  coordinate system, the source process is the process such that mydist=0.
*/
      if( ( mydist = MYPROC - SRCPROC ) < 0 ) mydist += NPROCS;
/*
*  When mydist <  nblocks - ilocblk * NPROCS, I own ilocblk + 1 full blocks of
*  size NB since I am not the source process, i.e. II = ( ilocblk + 1 ) * NB.
*  When mydist >= nblocks - ilocblk * NPROCS and I don't own IG, I own ilocblk
*  full blocks of size NB, i.e. II = ilocblk * NB, otherwise I own ilocblk
*  blocks and IG, in which case IG can be written as INB + (nblocks-1)*NB + IL
*  and II = ilocblk*NB + IL = IG - INB + ( ilocblk - nblocks + 1 )*NB.
*/
      if( nblocks < NPROCS )
      {
         mydist -= nblocks;
         return( ( ( mydist < 0 ) ? NB :
                   ( ( MYPROC == proc ) ? IG + ( 1 - nblocks ) * NB : 0 ) ) );
      }
      else
      {
         ilocblk = nblocks / NPROCS;
         mydist -= nblocks - ilocblk * NPROCS;
         return( ( ( mydist < 0 ) ? ( ilocblk + 1 ) * NB :
                   ( ( MYPROC == proc ) ?
                   ( ilocblk - nblocks + 1 ) * NB + IG : ilocblk * NB ) ) );
      }
   }
/*
*  End of PB_Cg2lrem
*/
}