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