00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 #include "idxl.h" 
00009 #include "idxl_layout.h"
00010 #include <string.h> 
00011 #include <math.h>
00012 #include <limits.h>
00013 #include <float.h> 
00014 typedef unsigned char byte;
00015 
00016 int IDXL_Layout::type_size(int dataType,const char *callingRoutine)
00017 {
00018     switch(dataType) {
00019       case IDXL_BYTE : return 1;
00020       case IDXL_INT : return sizeof(int);
00021       case IDXL_REAL : return sizeof(float);
00022       case IDXL_DOUBLE : return sizeof(double);
00023       case IDXL_LONG_DOUBLE : return sizeof(long double); 
00024       case IDXL_INDEX_0 : return sizeof(int);
00025       case IDXL_INDEX_1 : return sizeof(int);
00026       default: IDXL_Abort(callingRoutine,"Expected an IDXL data type, but got %d",dataType);
00027     }
00028     return -1;
00029 }
00030 
00031 const char *IDXL_Layout::type_name(int dataType,const char *callingRoutine) 
00032 {
00033     switch(dataType) {
00034       case IDXL_BYTE : return "IDXL_BYTE";
00035       case IDXL_INT : return "IDXL_INT";
00036       case IDXL_REAL : return "IDXL_REAL";
00037       case IDXL_DOUBLE : return "IDXL_DOUBLE";
00038       case IDXL_LONG_DOUBLE : return "IDXL_LONG_DOUBLE";
00039       case IDXL_INDEX_0 : return "IDXL_INDEX_0";
00040       case IDXL_INDEX_1 : return "IDXL_INDEX_1";
00041       default: break;
00042     }
00043     return "(unknown IDXL datatype)";
00044 }
00045 
00046 
00047 
00048 
00049 
00050 template<class T>
00051 inline void assignOne(T* lhs, T val) { *lhs = val; }
00052 
00053 template<class T>
00054 inline void assignOne(T* lhs, const T *rhs) { *lhs = *rhs; }
00055 
00056 template<class T>
00057 inline void sumOne(T* lhs, const T* rhs) { *lhs += *rhs; }
00058 
00059 template<class T>
00060 inline void prodOne(T* lhs, const T* rhs) { *lhs *= *rhs; }
00061 
00062 template<class T>
00063 inline void maxOne(T* lhs, const T* rhs) { *lhs = (*lhs > *rhs) ? *lhs : *rhs; }
00064 
00065 template<class T>
00066 inline void minOne(T* lhs, const T* rhs) { *lhs = (*lhs < *rhs) ? *lhs : *rhs; }
00067 
00068 
00069 
00070 
00071 
00072 #define oneToFn(oneFn,gatherName) \
00073 template<class T> \
00074 void gatherName(T *dest,const byte *src,const IDXL_Layout *srcLayout) { \
00075     src+=srcLayout->offset; \
00076     int skew=srcLayout->skew; \
00077     int i=0, width=srcLayout->width; \
00078     for (i=0;i<width;i++) { \
00079         oneFn(dest,(const T *)src); \
00080         dest++; \
00081         src+=skew; \
00082     } \
00083 } \
00084  \
00085 template void gatherName(byte *dest,const byte *src,const IDXL_Layout *srcLayout); \
00086 template void gatherName(int *dest,const byte *src,const IDXL_Layout *srcLayout); \
00087 template void gatherName(float *dest,const byte *src,const IDXL_Layout *srcLayout); \
00088 template void gatherName(double *dest,const byte *src,const IDXL_Layout *srcLayout); \
00089 template void gatherName(long double *dest,const byte *src,const IDXL_Layout *srcLayout);
00090 
00091 oneToFn(sumOne,sumFn)
00092 oneToFn(prodOne,prodFn)
00093 oneToFn(maxOne,maxFn)
00094 oneToFn(minOne,minFn)
00095 
00096 typedef void (*byteCombineFn)(byte *dest,const byte *src,const IDXL_Layout *srcLayout);
00097 typedef void (*intCombineFn)(int *dest,const byte *src,const IDXL_Layout *srcLayout);
00098 typedef void (*floatCombineFn)(float *dest,const byte *src,const IDXL_Layout *srcLayout);
00099 typedef void (*doubleCombineFn)(double *dest,const byte *src,const IDXL_Layout *srcLayout);
00100 typedef void (*longDoubleCombineFn)(long double *dest,const byte *src,const IDXL_Layout *srcLayout);
00101 
00102 
00103 template<class T>
00104 inline void assignFn(int len,T *dest,T val) {
00105   for (int i=0;i<len;i++) dest[i]=val;
00106 }
00107 
00108 
00109 
00110 void reduction_initialize(const IDXL_Layout& dt, void *lhs, int op,const char *callingRoutine)
00111 {
00112   switch(op) {
00113     case IDXL_SUM:
00114       switch(dt.type) {
00115         case IDXL_BYTE : assignFn<unsigned char>(dt.width,(byte*)lhs, (byte)0); break;
00116         case IDXL_INT : assignFn<int>(dt.width,(int*)lhs, 0); break;
00117         case IDXL_REAL : assignFn<float>(dt.width,(float*)lhs, (float)0.0); break;
00118         case IDXL_DOUBLE : assignFn<double>(dt.width,(double*)lhs, 0.0); break;
00119         case IDXL_LONG_DOUBLE : assignFn<long double>(dt.width,(long double*)lhs, 0.0L); break;
00120         default: IDXL_Abort(callingRoutine,"Invalid IDXL data type %d",dt.type);
00121       }
00122       break;
00123     case IDXL_PROD:
00124       switch(dt.type) {
00125         case IDXL_BYTE : assignFn<unsigned char>(dt.width,(byte*)lhs, (byte)1); break;
00126         case IDXL_INT : assignFn<int>(dt.width,(int*)lhs, 1); break;
00127         case IDXL_REAL : assignFn<float>(dt.width,(float*)lhs, (float)1.0); break;
00128         case IDXL_DOUBLE : assignFn<double>(dt.width,(double*)lhs, 1.0); break;
00129         case IDXL_LONG_DOUBLE : assignFn<long double>(dt.width,(long double*)lhs, 1.0L); break;
00130       }
00131       break;
00132     case IDXL_MAX:
00133       switch(dt.type) {
00134         case IDXL_BYTE : assignFn<unsigned char>(dt.width,(byte*)lhs, (byte)CHAR_MIN); break;
00135         case IDXL_INT : assignFn<int>(dt.width,(int*)lhs, INT_MIN); break;
00136         case IDXL_REAL : assignFn<float>(dt.width,(float*)lhs, (float)FLT_MIN); break;
00137         case IDXL_DOUBLE : assignFn<double>(dt.width,(double*)lhs, DBL_MIN); break;
00138         case IDXL_LONG_DOUBLE : assignFn<long double>(dt.width,(long double*)lhs, LDBL_MIN); break;
00139       }
00140       break;
00141     case IDXL_MIN:
00142       switch(dt.type) {
00143         case IDXL_BYTE : assignFn<unsigned char>(dt.width,(byte*)lhs, (byte)CHAR_MAX); break;
00144         case IDXL_INT : assignFn<int>(dt.width,(int*)lhs, INT_MAX); break;
00145         case IDXL_REAL : assignFn<float>(dt.width,(float*)lhs, FLT_MAX); break;
00146         case IDXL_DOUBLE : assignFn<double>(dt.width,(double*)lhs, DBL_MAX); break;
00147         case IDXL_LONG_DOUBLE : assignFn<long double>(dt.width,(long double*)lhs, LDBL_MAX); break;
00148       }
00149       break;
00150     default: IDXL_Abort(callingRoutine,"Expected an IDXL reduction type, but got %d",op);
00151   }
00152 }
00153 
00154 
00155 
00156 #define idxl_type_return(type,fn) \
00157       switch(type) {\
00158         case IDXL_BYTE : return (reduction_combine_fn)(byteCombineFn)fn;\
00159         case IDXL_INT : return (reduction_combine_fn)(intCombineFn)fn;\
00160         case IDXL_REAL : return (reduction_combine_fn)(floatCombineFn)fn;\
00161         case IDXL_DOUBLE : return (reduction_combine_fn)(doubleCombineFn)fn;\
00162         case IDXL_LONG_DOUBLE : return (reduction_combine_fn)(longDoubleCombineFn)fn;\
00163       }
00164 
00165 reduction_combine_fn reduction_combine(const IDXL_Layout& dt, int op,const char *callingRoutine)
00166 {
00167   switch(op) {
00168     case IDXL_SUM: idxl_type_return(dt.type, sumFn); break;
00169     case IDXL_PROD: idxl_type_return(dt.type, prodFn); break;
00170     case IDXL_MIN: idxl_type_return(dt.type, minFn); break;
00171     case IDXL_MAX: idxl_type_return(dt.type, maxFn); break;
00172     default: IDXL_Abort(callingRoutine,"Expected an IDXL reduction type, but got %d",op);
00173   }
00174   IDXL_Abort(callingRoutine,"Expected an IDXL data type, but got %d",dt.type);
00175   return NULL;
00176 }
00177 
00178 
00179 
00180 #define idxl_type_call(type,fn,args) \
00181       switch(type) {\
00182         case IDXL_BYTE : fn args(byte); break; \
00183         case IDXL_INT : fn args(int); break; \
00184         case IDXL_REAL : fn args(float); break; \
00185         case IDXL_DOUBLE : fn args(double); break; \
00186         case IDXL_LONG_DOUBLE : fn args(long double); break; \
00187       }
00188 
00189 
00190 #define scatterGatherArgs(type) \
00191     (v_user, nIndices,indices, IDXL_LAYOUT_CALL(*this), (type *)v_compressed)
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 
00200 template <class T>
00201 inline void gatherUserData(const void *user,int nIndices,const int *indices,
00202         IDXL_LAYOUT_PARAM,T *compressed) 
00203 {
00204     for (int r=0;r<nIndices;r++) {
00205         int sr=indices[r];
00206         if(sr!=-1) {
00207           for (int c=0;c<width;c++) {
00208             compressed[c]=IDXL_LAYOUT_DEREF(T,user,sr,c);
00209           }
00210           compressed+=width;
00211         }
00212     }
00213 }
00214 
00219 void IDXL_Layout::gather(int nIndices,const int *indices,
00220            const void *v_user,void *v_compressed) const
00221 {
00222   idxl_type_call(this->type, gatherUserData, scatterGatherArgs);
00223 }
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 template <class T>
00232 inline void scatterUserData(void *user,int nIndices,const int *indices,
00233         IDXL_LAYOUT_PARAM,const T *compressed) 
00234 {
00235     for (int r=0;r<nIndices;r++) {
00236         int sr=indices[r];
00237         for (int c=0;c<width;c++)
00238             IDXL_LAYOUT_DEREF(T,user,sr,c)=compressed[c];
00239         compressed+=width;
00240     }
00241 }
00242 
00247 void IDXL_Layout::scatter(int nIndices,const int *indices,
00248            const void *v_compressed,void *v_user) const
00249 {
00250   idxl_type_call(this->type, scatterUserData, scatterGatherArgs);
00251 }
00252 
00253 
00254 
00255 
00256 
00257 
00258 template <class T>
00259 inline void scatterAddUserData(void *user,int nIndices,const int *indices,
00260         IDXL_LAYOUT_PARAM,const T *compressed) 
00261 {
00262     for (int r=0;r<nIndices;r++) {
00263         int sr=indices[r];
00264         if(sr!=-1) {
00265           for (int c=0;c<width;c++){
00266             IDXL_LAYOUT_DEREF(T,user,sr,c)+=compressed[c];
00267           }
00268           compressed+=width;
00269         }
00270     }
00271 }
00272 
00277 void IDXL_Layout::scatteradd(int nIndices,const int *indices,
00278            const void *v_compressed,void *v_user) const
00279 {
00280   idxl_type_call(this->type, scatterAddUserData, scatterGatherArgs);
00281 }
00282 
00283 
00284 
00285 
00286 void IDXL_Layout_List::badLayout(IDXL_Layout_t l,const char *callingRoutine) const
00287 {
00288     IDXL_Abort(callingRoutine,"Expected an IDXL_Layout_t, got %d",l);
00289 }
00290 
00291 IDXL_Layout_List::IDXL_Layout_List() {
00292     for (int i=0;i<MAX_DT;i++) list[i]=NULL;
00293 }
00294 void IDXL_Layout_List::pup(PUP::er &p) {
00295     for (int i=0;i<MAX_DT;i++) {
00296         int isNULL=(list[i]==NULL);
00297         p|isNULL;
00298         if (!isNULL) {
00299             if (list[i]==NULL) list[i]=new IDXL_Layout();
00300             p|*list[i];
00301         }
00302     }
00303 }
00304 IDXL_Layout_List::~IDXL_Layout_List() {
00305     empty();
00306 }
00308 void IDXL_Layout_List::empty(void) {
00309     for (int i=0;i<MAX_DT;i++) 
00310         if (list[i]!=NULL) {
00311             delete list[i];
00312             list[i]=NULL;
00313         }
00314 }
00315 
00316 IDXL_Layout_t IDXL_Layout_List::put(const IDXL_Layout &dt) {
00317     for (int i=0;i<MAX_DT;i++) 
00318         if (list[i]==NULL) {
00319             list[i]=new IDXL_Layout(dt);
00320             return FIRST_DT+i;
00321         }
00322     
00323     IDXL_Abort("","Registered too many IDXL_Layouts! (only have room for %d)",MAX_DT);
00324     return 0; 
00325 }
00326 void IDXL_Layout_List::destroy(IDXL_Layout_t l,const char *callingRoutine) {
00327     check(l,callingRoutine);
00328     int i=l-FIRST_DT;
00329     delete list[i];
00330     list[i]=NULL;
00331 }
00332