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