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