Provide a crude comparison operator< to permit CkArrayIndex in comparison-based conta...
[charm.git] / src / ck-core / ckarrayindex.h
1 #ifndef CKARRAYINDEX_H
2 #define CKARRAYINDEX_H
3
4 #include "pup.h"
5 #include "ckhashtable.h"
6 #include "charm.h"
7
8 /// Max number of integers in an array index
9 #ifndef CK_ARRAYINDEX_MAXLEN
10     #define CK_ARRAYINDEX_MAXLEN 3
11 #endif
12
13 #ifndef CK_ARRAYLISTENER_MAXLEN
14 # define CK_ARRAYLISTENER_MAXLEN 3
15 #endif
16
17 /** @warning: fwd declaration of child class to support crazy ptr cast
18  */
19 class CkArrayIndex;
20
21
22 /**
23  * Base class for array index objects used in charm.
24  *
25  * An array index is just a hash key; a run of integers
26  * used to look up an object in a hash table.
27  *
28  * @note: Should define *all* data members that make up an index object.
29  * @warning: Do not instantiate! Always create and use a child class
30  * @warning: Do not add constructors / destructors. Class participates in unions
31  *
32  * @note: Should be completely invisible to most client code except those that directly
33  * need to put index objects in unions. This happens only in a few entities in the charm
34  * codebase and should not happen at all in user codes.
35  */
36 struct CkArrayIndexBase
37 {
38     public:
39         ///Length of index in *integers*
40         short int nInts;
41         ///Number of dimensions in this index, not valid for user-defined indices
42         short int dimension;
43         /// The actual index data
44         union {
45             int index[CK_ARRAYINDEX_MAXLEN];
46             short int indexShorts[2 * CK_ARRAYINDEX_MAXLEN];
47         };
48
49         /// Obtain usable object from base object. @warning: Dangerous pointer cast to child class!!!
50         inline CkArrayIndex& asChild() const { return *(CkArrayIndex*)this; }
51
52         /// Permit serialization
53         void pup(PUP::er &p)
54         {
55             p|nInts;
56             p|dimension;
57             for (int i=0;i<nInts;i++) p|index[i];
58         }
59 };
60
61
62
63 /**
64  * Actual array index class intended for regular use
65  *
66  * @warning: Put all data members in base class or they may not be transmitted
67  * in envelopes or callbacks (basically in any entity that stores indices in a
68  * union). Only add behaviors to this class.
69  */
70 class CkArrayIndex: public CkArrayIndexBase
71 {
72     public:
73         /// Default
74         CkArrayIndex() { nInts=0; dimension=0; for (int i=0; i<CK_ARRAYINDEX_MAXLEN; i++) index[i] = 0; }
75
76         CkArrayIndex(int idx) {init(1,1,idx);};
77
78         /// Return a pointer to the actual index data
79         int *data(void)             {return index; }
80         /// Return a const pointer to the actual index data
81         const int *data(void) const {return index; }
82
83         /// Return the total number of elements (assuming a dense chare array)
84         int getCombinedCount(void) const
85         {
86             if      (dimension == 1) return data()[0];
87             else if (dimension == 2) return data()[0] * data()[1];
88             else if (dimension == 3) return data()[0] * data()[1] * data()[2];
89             else return 0;
90         }
91
92         /// Used for debug prints elsewhere
93         void print() { CmiPrintf("%d: %d %d %d\n", nInts, index[0], index[1], index[2]); }
94
95         /// Equality comparison
96         CmiBool operator==(const CkArrayIndex& idx) const
97         {
98             if (nInts != idx.nInts) return CmiFalse;
99             for (int i=0; i<nInts; i++)
100                 if (index[i] != idx.index[i]) return CmiFalse;
101             return CmiTrue;
102         }
103
104         /// These routines allow CkArrayIndex to be used in a CkHashtableT
105         inline CkHashCode hash(void) const
106         {
107             register int i;
108             register const int *d=data();
109             register CkHashCode ret=d[0];
110             for (i=1;i<nInts;i++)
111                 ret +=circleShift(d[i],10+11*i)+circleShift(d[i],9+7*i);
112             return ret;
113         }
114         ///
115         static CkHashCode staticHash(const void *a,size_t) { return ((const CkArrayIndex *)a)->hash(); }
116         ///
117         inline int compare(const CkArrayIndex &idx) const { return (idx == *this); }
118         ///
119         static int staticCompare(const void *a,const void *b, size_t)
120         { return (*(const CkArrayIndex *)a == *(const CkArrayIndex *)b); }
121
122         /**
123          * @note: input arrayID is ignored
124          * @todo: Chee Wai Lee had a FIXME note attached to this method because he
125          * felt it was a temporary solution
126          */
127         CmiObjId *getProjectionID(int arrayID)
128         {
129             CmiObjId *ret = new CmiObjId;
130             int i;
131             const int *data=this->data();
132             if (OBJ_ID_SZ>=this->nInts)
133             {
134                 for (i=0;i<this->nInts;i++)
135                     ret->id[i]=data[i];
136                 for (i=this->nInts;i<OBJ_ID_SZ;i++)
137                     ret->id[i]=0;
138             }
139             else
140             {
141                 //Must hash array index into LBObjid
142                 int j;
143                 for (j=0;j<OBJ_ID_SZ;j++)
144                     ret->id[j]=data[j];
145                 for (i=0;i<this->nInts;i++)
146                     for (j=0;j<OBJ_ID_SZ;j++)
147                         ret->id[j]+=circleShift(data[i],22+11*i*(j+1))+
148                             circleShift(data[i],21-9*i*(j+1));
149             }
150             return ret;
151         }
152
153     protected:
154         inline void init(const short num, const short dims, const int x, const int y=0, const int z=0)
155         {
156             nInts = num;
157             dimension = dims;
158             index[0] = x;
159             index[1] = y;
160             index[2] = z;
161             for (int i=3; i < CK_ARRAYINDEX_MAXLEN; i++)
162                 index[i] = 0;
163         }
164
165         inline void init(const short num, const short dims,
166                          const short u, const short v, const short w,
167                          const short x, const short y=0, const short z=0)
168         {
169             nInts = num;
170             dimension = dims;
171             indexShorts[0] = u;
172             indexShorts[1] = v;
173             indexShorts[2] = w;
174             indexShorts[3] = x;
175             indexShorts[4] = y;
176             indexShorts[5] = z;
177             for (int i=6; i < 2 * CK_ARRAYINDEX_MAXLEN; i++)
178                 indexShorts[i] = 0;
179         }
180
181
182         /// A very crude comparison operator to enable using in comparison-based containers
183         friend bool operator< (const CkArrayIndex &lhs, const CkArrayIndex &rhs)
184         {
185             if (lhs.nInts != rhs.nInts)
186                 CkAbort("cannot compare two indices of different cardinality");
187             for (int i = 0; i < lhs.nInts; i++)
188                 if (lhs.data()[i] >= rhs.data()[i])
189                     return false;
190             return true;
191         }
192 };
193
194
195 /**
196  * Support applications and other charm codes that still use the (now dead)
197  * CkArrayIndexMax class to manipulate array indices. All the functionality is
198  * now incorporated into the CkArrayIndex base class itself.
199  *
200  * It is recommended that newer code directly use the base class when there is
201  * need to handle an array index.
202  *
203  * @todo: After at least one minor release announcing the deprecation,
204  * CkArrayIndexMax should no longer be supported.
205  */
206 typedef CkArrayIndex CkArrayIndexMax;
207
208 class CkArray;
209
210 class CkArrayID {
211         CkGroupID _gid;
212 public:
213         CkArrayID() : _gid() { }
214         CkArrayID(CkGroupID g) :_gid(g) {}
215         inline void setZero(void) {_gid.setZero();}
216         inline int isZero(void) const {return _gid.isZero();}
217         operator CkGroupID() const {return _gid;}
218         CkArray *ckLocalBranch(void) const
219                 { return (CkArray *)CkLocalBranch(_gid); }
220         static CkArray *CkLocalBranch(CkArrayID id)
221                 { return (CkArray *)::CkLocalBranch(id); }
222         void pup(PUP::er &p) {p | _gid; }
223         int operator == (const CkArrayID& other) const {
224                 return (_gid == other._gid);
225         }
226     friend bool operator< (const CkArrayID &lhs, const CkArrayID &rhs) {
227         return (lhs._gid < rhs._gid);
228     }
229 };
230 PUPmarshall(CkArrayID)
231
232 #endif // CKARRAYINDEX_H
233