00001 #ifndef CKARRAYINDEX_H
00002 #define CKARRAYINDEX_H
00003
00004 #include "pup.h"
00005 #include "ckhashtable.h"
00006 #include "charm.h"
00007 #include "objid.h"
00008 #include <vector>
00009 #include <math.h>
00010
00012 #ifndef CK_ARRAYINDEX_MAXLEN
00013 #define CK_ARRAYINDEX_MAXLEN 3
00014 #endif
00015
00016 #ifndef CK_ARRAYLISTENER_MAXLEN
00017 # define CK_ARRAYLISTENER_MAXLEN 2
00018 #endif
00019
00022 class CkArrayIndex;
00023
00024
00039 struct CkArrayIndexBase
00040 {
00041 public:
00043 short unsigned int nInts;
00045 short unsigned int dimension;
00047 union {
00048 int index[CK_ARRAYINDEX_MAXLEN];
00049 short int indexShorts[2 * CK_ARRAYINDEX_MAXLEN];
00050 };
00051
00053 inline CkArrayIndex& asChild() const { return *(CkArrayIndex*)this; }
00054
00056 inline void pup(PUP::er &p)
00057 {
00058 p((char *)this, sizeof(CkArrayIndexBase));
00059 }
00060
00061 bool operator==(CkArrayIndexBase &other) {
00062 if(nInts != other.nInts) return false;
00063 if(dimension != other.dimension) return false;
00064 for (int i=0;i<nInts;i++) {
00065 if(index[i] != other.index[i]) return false;
00066 }
00067 return true;
00068 }
00069
00070 };
00071 PUPbytes(CkArrayIndexBase)
00072
00073
00074
00075
00082 class CkArrayIndex: public CkArrayIndexBase
00083 {
00084 public:
00086 CkArrayIndex() { nInts=0; dimension=0; for (int i=0; i<CK_ARRAYINDEX_MAXLEN; i++) index[i] = 0; }
00087
00089 CkArrayIndex(int ndims, int dims[]) {
00090 init_nd(ndims, dims);
00091 }
00092
00094 CkArrayIndex(int ndims, int val) {
00095 std::vector<int> dims(ndims, val);
00096 init_nd(ndims, dims.data());
00097 }
00098
00099 explicit CkArrayIndex(int idx) {init(1,1,idx);};
00100
00102 int *data(void) {return index; }
00104 const int *data(void) const {return index; }
00105
00107 short getDimension(void) const { return dimension; }
00109 short *shortData(void) { return indexShorts; }
00111 const short *shortData(void) const { return indexShorts; }
00112
00114 int getCombinedCount(void) const
00115 {
00116 if (dimension == 1) return data()[0];
00117 else if (dimension == 2) return data()[0] * data()[1];
00118 else if (dimension == 3) return data()[0] * data()[1] * data()[2];
00119 else if (dimension == 4) return shortData()[0] * shortData()[1] * shortData()[2] *
00120 shortData()[3];
00121 else if (dimension == 5) return shortData()[0] * shortData()[1] * shortData()[2] *
00122 shortData()[3] * shortData()[4];
00123 else if (dimension == 6) return shortData()[0] * shortData()[1] * shortData()[2] *
00124 shortData()[3] * shortData()[4] * shortData()[5];
00125 else return 0;
00126 }
00127
00129 void print() const {
00130 if (dimension < 4) CmiPrintf("%d: %d %d %d\n", dimension, index[0], index[1], index[2]);
00131 else CmiPrintf("%d: %d %d %d %d %d %d\n", dimension, indexShorts[0], indexShorts[1], indexShorts[2],
00132 indexShorts[3], indexShorts[4], indexShorts[5]);
00133 }
00134
00136 bool operator==(const CkArrayIndex& idx) const
00137 {
00138 if (nInts != idx.nInts) return false;
00139 for (int i=0; i<nInts; i++)
00140 if (index[i] != idx.index[i]) return false;
00141 return true;
00142 }
00143
00145 inline CkHashCode hash(void) const
00146 {
00147 int i;
00148 const int *d=data();
00149 CkHashCode ret=d[0];
00150 for (i=0;i<nInts;i++)
00151 ret +=circleShift(d[i],10+11*i)+circleShift(d[i],9+7*i);
00152 return ret;
00153 }
00155 static CkHashCode staticHash(const void *a,size_t) { return ((const CkArrayIndex *)a)->hash(); }
00157 inline int compare(const CkArrayIndex &idx) const { return (idx == *this); }
00159 static int staticCompare(const void *a,const void *b, size_t)
00160 { return (*(const CkArrayIndex *)a == *(const CkArrayIndex *)b); }
00161
00166 CmiObjId *getProjectionID() const
00167 {
00168 CmiObjId *ret = new CmiObjId;
00169 int i;
00170 const int *data=this->data();
00171 if (OBJ_ID_SZ>=this->nInts)
00172 {
00173 for (i=0;i<this->nInts;i++)
00174 ret->id[i]=data[i];
00175 for (i=this->nInts;i<OBJ_ID_SZ;i++)
00176 ret->id[i]=0;
00177 }
00178 else
00179 {
00180
00181 int j;
00182 for (j=0;j<OBJ_ID_SZ;j++)
00183 ret->id[j]=data[j];
00184 for (i=0;i<this->nInts;i++)
00185 for (j=0;j<OBJ_ID_SZ;j++)
00186 ret->id[j]+=circleShift(data[i],22+11*i*(j+1))+
00187 circleShift(data[i],21-9*i*(j+1));
00188 }
00189 return ret;
00190 }
00191
00192 protected:
00193 inline void init(const short num, const short dims, const int x, const int y=0, const int z=0)
00194 {
00195 nInts = num;
00196 dimension = dims;
00197 index[0] = x;
00198 index[1] = y;
00199 index[2] = z;
00200 for (int i=3; i < CK_ARRAYINDEX_MAXLEN; i++)
00201 index[i] = 0;
00202 }
00203
00204 inline void init(const short num, const short dims,
00205 const short u, const short v, const short w,
00206 const short x, const short y=0, const short z=0)
00207 {
00208 nInts = num;
00209 dimension = dims;
00210 indexShorts[0] = u;
00211 indexShorts[1] = v;
00212 indexShorts[2] = w;
00213 indexShorts[3] = x;
00214 indexShorts[4] = y;
00215 indexShorts[5] = z;
00216 for (int i=6; i < 2 * CK_ARRAYINDEX_MAXLEN; i++)
00217 indexShorts[i] = 0;
00218 }
00219
00220 inline void init_nd(int ndims, int dims[]) {
00221 switch (ndims) {
00222 case 1: init(1,1,dims[0]); break;
00223 case 2: init(2,2,dims[0],dims[1]); break;
00224 case 3: init(3,3,dims[0],dims[1],dims[2]); break;
00225 case 4: init(2,4,dims[0],dims[1],dims[2],dims[3]); break;
00226 case 5: init(3,5,dims[0],dims[1],dims[2],dims[3],dims[4]); break;
00227 case 6: init(3,6,dims[0],dims[1],dims[2],dims[3],dims[4],dims[5]); break;
00228 default: CkAbort("CKArrayIndex() unsupported number of dimensions\n");
00229 }
00230 }
00231
00232
00234 friend bool operator< (const CkArrayIndex &lhs, const CkArrayIndex &rhs)
00235 {
00236 #if CMK_ERROR_CHECKING
00237 if (lhs.nInts != rhs.nInts)
00238 CkAbort("cannot compare two indices of different cardinality");
00239 #endif
00240
00241 for (int i = 0; i < lhs.nInts; i++)
00242 if (lhs.data()[i] < rhs.data()[i])
00243 return true;
00244 else if (rhs.data()[i] < lhs.data()[i])
00245 return false;
00246 return false;
00247 }
00248 };
00249
00250
00262 typedef CkArrayIndex CkArrayIndexMax;
00263
00264 class CkArray;
00265
00266 struct CkArrayID {
00267 private:
00268 CkGroupID _gid;
00269 public:
00270 CkArrayID() : _gid() { }
00271 CkArrayID(CkGroupID g) :_gid(g) {}
00272 inline void setZero(void) {_gid.setZero();}
00273 inline bool isZero(void) const {return _gid.isZero();}
00274 operator CkGroupID() const {return _gid;}
00275 CkArray *ckLocalBranch(void) const
00276 { return (CkArray *)CkLocalBranch(_gid); }
00277 static CkArray *CkLocalBranch(CkArrayID id)
00278 { return (CkArray *)::CkLocalBranch(id); }
00279 void pup(PUP::er &p) {p | _gid; }
00280 bool operator == (const CkArrayID& other) const {
00281 return (_gid == other._gid);
00282 }
00283 friend bool operator< (const CkArrayID &lhs, const CkArrayID &rhs) {
00284 return (lhs._gid < rhs._gid);
00285 }
00286 };
00287 PUPmarshall(CkArrayID)
00288
00289 typedef int CkIndex1D;
00290 typedef struct {int x,y;} CkIndex2D;
00291 PUPbytes(CkIndex2D)
00292 typedef struct {int x,y,z;} CkIndex3D;
00293 PUPbytes(CkIndex3D)
00294 typedef struct {short int w,x,y,z;} CkIndex4D;
00295 PUPbytes(CkIndex4D)
00296 typedef struct {short int v,w,x,y,z;} CkIndex5D;
00297 PUPbytes(CkIndex5D)
00298 typedef struct {short int x1,y1,z1,x2,y2,z2;} CkIndex6D;
00299 PUPbytes(CkIndex6D)
00300 typedef struct {int data[CK_ARRAYINDEX_MAXLEN];} CkIndexMax;
00301 PUPbytes(CkIndexMax)
00302
00303
00304 class CkArrayIndex1D : public CkArrayIndex {
00305 public:
00306 CkArrayIndex1D() {}
00307
00308 CkArrayIndex1D(int i0) { init(1, 1, i0); }
00309 };
00310 class CkArrayIndex2D : public CkArrayIndex {
00311 public:
00312 CkArrayIndex2D() {}
00313 CkArrayIndex2D(int i0,int i1) { init(2, 2, i0, i1); }
00314 CkArrayIndex2D(CkIndex2D idx) { init(2, 2, idx.x, idx.y); }
00315 };
00316 class CkArrayIndex3D : public CkArrayIndex {
00317 public:
00318 CkArrayIndex3D() {}
00319 CkArrayIndex3D(int i0,int i1,int i2) { init(3, 3, i0, i1, i2); }
00320 CkArrayIndex3D(CkIndex3D idx) { init(3, 3, idx.x, idx.y, idx.z); }
00321 };
00322 class CkArrayIndex4D : public CkArrayIndex {
00323 public:
00324 CkArrayIndex4D(){}
00325 CkArrayIndex4D(short int i0,short int i1,short int i2,short int i3) { init(2, 4, i0, i1, i2, i3); }
00326 CkArrayIndex4D(CkIndex4D idx) { init(2, 4, idx.w, idx.x, idx.y, idx.z); }
00327 };
00328 class CkArrayIndex5D : public CkArrayIndex {
00329 public:
00330 CkArrayIndex5D() {}
00331 CkArrayIndex5D(short int i0,short int i1,short int i2,short int i3,short int i4) { init(3, 5, i0, i1, i2, i3, i4); }
00332 CkArrayIndex5D(CkIndex5D idx) { init(3, 5, idx.v, idx.w, idx.x, idx.y, idx.z); }
00333 };
00334 class CkArrayIndex6D : public CkArrayIndex {
00335 public:
00336 CkArrayIndex6D(){}
00337 CkArrayIndex6D(short int i0,short int i1,short int i2,short int i3,short int i4,short int i5) { init(3, 6, i0, i1, i2, i3, i4, i5); }
00338 CkArrayIndex6D(CkIndex6D idx) { init(3, 6, idx.x1, idx.y1, idx.z1, idx.x2, idx.y2, idx.z2); }
00339 };
00340
00344 template <class object>
00345 class CkArrayIndexT : public CkArrayIndex {
00346 public:
00347 object obj;
00348 CkArrayIndexT(const object &srcObj) {obj=srcObj;
00349 nInts=sizeof(obj)/sizeof(int);
00350 dimension=0; }
00351 };
00352
00353 namespace ck {
00354 class ArrayIndexCompressor {
00355 public:
00356 virtual CmiUInt8 compress(const CkArrayIndex &idx) = 0;
00357 virtual CkArrayIndex decompress(CmiUInt8 id) = 0;
00358 };
00359
00360 class FixedArrayIndexCompressor : public ArrayIndexCompressor {
00361 public:
00364 static FixedArrayIndexCompressor* make(const CkArrayIndex &bounds) {
00365 if (bounds.nInts == 0)
00366 return NULL;
00367
00368 char dims = bounds.dimension;
00369 char bits[6];
00370 unsigned int sum = 0;
00371 bool shorts = bounds.dimension > 3;
00372
00373 for (int i = 0; i < bounds.dimension; ++i) {
00374 int bound = shorts ? bounds.indexShorts[i] : bounds.index[i];
00375 unsigned int b = bitCount(bound);
00376 bits[i] = b;
00377 sum += b;
00378 }
00379
00380 if (sum > 48)
00381 return NULL;
00382
00383 return new FixedArrayIndexCompressor(dims, bits);
00384 }
00385
00387 CmiUInt8 compress(const CkArrayIndex &idx) {
00388 CkAssert(idx.dimension == dims);
00389
00390 CmiUInt8 eid = 0;
00391
00392 bool shorts = idx.dimension > 3;
00393
00394 for (unsigned int i = 0; i < idx.dimension; ++i) {
00395 unsigned int numBits = bitsPerDim[i];
00396 unsigned int thisDim = shorts ? idx.indexShorts[i] : idx.index[i];
00397 CkAssert(thisDim < (1UL << numBits));
00398 eid = (eid << numBits) | thisDim;
00399 }
00400 return eid;
00401 }
00402
00403 CkArrayIndex decompress(CmiUInt8 id) {
00404 int ix[6];
00405 for (int i = dims - 1; i >= 0; --i) {
00406 int bits = bitsPerDim[i];
00407 ix[i] = id & ((1 << bits) - 1);
00408 id >>= bits;
00409 }
00410
00411 switch(dims) {
00412 case 1:
00413 return CkArrayIndex1D(ix[0]);
00414 case 2:
00415 return CkArrayIndex2D(ix[0], ix[1]);
00416 case 3:
00417 return CkArrayIndex3D(ix[0], ix[1], ix[2]);
00418 case 4:
00419 return CkArrayIndex4D(ix[0], ix[1], ix[2], ix[3]);
00420 case 5:
00421 return CkArrayIndex5D(ix[0], ix[1], ix[2], ix[3], ix[4]);
00422 default:
00423 return CkArrayIndex6D(ix[0], ix[1], ix[2], ix[3], ix[4], ix[5]);
00424 }
00425 }
00426
00427 private:
00428 FixedArrayIndexCompressor(char dims, char* bits)
00429 : dims(dims)
00430 { for (int i = 0; i < dims; i++) bitsPerDim[i] = bits[i]; }
00431 char bitsPerDim[6];
00432 char dims;
00433
00436 static unsigned int bitCount(int bound) {
00437 CkAssert(bound > 0);
00438
00439
00440 bound--;
00441 bound |= bound >> 1;
00442 bound |= bound >> 2;
00443 bound |= bound >> 4;
00444 bound |= bound >> 8;
00445 bound |= bound >> 16;
00446 bound++;
00447
00448
00449 unsigned int result = 0;
00450 while (bound >>= 1) {
00451 ++result;
00452 }
00453
00454 return result;
00455 }
00456 };
00457 }
00458
00459 #endif // CKARRAYINDEX_H
00460