Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShConcreteCTypeOpImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2005 Serious Hack Inc.
00004 // 
00005 // This software is provided 'as-is', without any express or implied
00006 // warranty. In no event will the authors be held liable for any damages
00007 // arising from the use of this software.
00008 // 
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it
00011 // freely, subject to the following restrictions:
00012 // 
00013 // 1. The origin of this software must not be misrepresented; you must
00014 // not claim that you wrote the original software. If you use this
00015 // software in a product, an acknowledgment in the product documentation
00016 // would be appreciated but is not required.
00017 // 
00018 // 2. Altered source versions must be plainly marked as such, and must
00019 // not be misrepresented as being the original software.
00020 // 
00021 // 3. This notice may not be removed or altered from any source
00022 // distribution.
00024 #ifndef SHCONCRETECTYPEOPIMPL_HPP 
00025 #define SHCONCRETECTYPEOPIMPL_HPP
00026 
00027 #include <numeric>
00028 #include <cmath>
00029 #include "ShEval.hpp"
00030 #include "ShVariant.hpp"
00031 #include "ShDebug.hpp"
00032 #include "ShError.hpp"
00033 #include "ShTypeInfo.hpp"
00034 
00035 namespace {
00037 template<typename T1, typename T2>
00038 T1 _sh_intpow(T1 x, T2 pow)
00039 {
00040         T1 result = 1;
00041         if(pow < 0) { 
00042                 x = 1 / x;
00043                 pow = -pow;
00044         }
00045         for(;pow; pow >>= 1, x *= x) {
00046                 if(pow & 1) result *= x;
00047         }
00048         return result;
00049 }
00050 }
00051 namespace SH {
00052 
00053 /* Partial specialization for different operations */ 
00054 
00055 /* The operators that depend on cmath different library functions
00056  * are specialized for float and double types in ShEval.cpp 
00057  * right now
00058  */
00059 // TODO make this cleaner?
00060 
00061 // TODO use the information from sdt's ShOperationInfo to decide
00062 // whether to do the ao/bo/co = 0 special case for scalar
00063 // ops where we step through the destination tuple but always
00064 // use the same element from the scalar src tuple. 
00065 
00066 // macros for componentwise operations
00067 // do a partial specialization on the class
00068 // and define the doop function
00069 #define SHCCTO_UNARY_OP(op, opsrc)\
00070 template<typename T>\
00071 struct ShConcreteCTypeOp<op, T>\
00072 { \
00073   typedef ShDataVariant<T, SH_HOST> Variant; \
00074   typedef Variant* DataPtr; \
00075   typedef const Variant* DataCPtr; \
00076 \
00077   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00078   {\
00079     SH_DEBUG_ASSERT(dest && a);\
00080     int ao = a->size() > 1;\
00081   \
00082     typename Variant::iterator D = dest->begin();\
00083     typename Variant::const_iterator A = a->begin();\
00084     for(; D != dest->end(); A += ao, ++D) {\
00085       (*D) = opsrc;\
00086     }\
00087   } \
00088 };
00089 
00090 
00091 #define SHCCTO_BINARY_OP(op, opsrc)\
00092 template<typename T>\
00093 struct ShConcreteCTypeOp<op, T>\
00094 { \
00095   typedef ShDataVariant<T, SH_HOST> Variant; \
00096   typedef Variant* DataPtr; \
00097   typedef const Variant* DataCPtr; \
00098 \
00099   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00100   {\
00101     SH_DEBUG_ASSERT(dest && a && b);\
00102     int ao = a->size() > 1;\
00103     int bo = b->size() > 1;\
00104   \
00105     typename Variant::iterator D = dest->begin();\
00106     typename Variant::const_iterator A, B;\
00107     A = a->begin();\
00108     B = b->begin();\
00109     for(; D != dest->end(); A += ao, B += bo, ++D) {\
00110       (*D) = opsrc;\
00111     }\
00112   } \
00113 };
00114 
00115 
00116 #define SHCCTO_TERNARY_OP(op, opsrc)\
00117 template<typename T>\
00118 struct ShConcreteCTypeOp<op, T>\
00119 { \
00120   typedef ShDataVariant<T, SH_HOST> Variant; \
00121   typedef Variant* DataPtr; \
00122   typedef const Variant* DataCPtr; \
00123 \
00124   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00125   {\
00126     SH_DEBUG_ASSERT(dest && a && b && c);\
00127     int ao = a->size() > 1;\
00128     int bo = b->size() > 1;\
00129     int co = c->size() > 1;\
00130   \
00131     typename Variant::iterator D = dest->begin();\
00132     typename Variant::const_iterator A, B, C;\
00133     A = a->begin();\
00134     B = b->begin();\
00135     C = c->begin();\
00136     for(; D != dest->end(); A += ao, B += bo, C += co, ++D) {\
00137       (*D) = opsrc;\
00138     }\
00139   }\
00140 };
00141 
00142 #define SHCCTO_OP_SPEC(T, op)\
00143 template<>\
00144 struct  \
00145 SH_DLLEXPORT \
00146 ShConcreteCTypeOp<op, T>\
00147 { \
00148   typedef ShDataVariant<T, SH_HOST> Variant; \
00149   typedef Variant* DataPtr; \
00150   typedef const Variant* DataCPtr; \
00151 \
00152   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0); \
00153 };
00154 
00155 #define SHCCTO_OP_CMATH_SPEC(op)\
00156   SHCCTO_OP_SPEC(double, op);\
00157   SHCCTO_OP_SPEC(float, op);
00158 
00159 // Note that some ops are currently NOT declared for integer types
00160 // (anything that is only specialized for double/float cmath functions 
00161 // will not work with ints)
00162 
00163 // Unary ops
00164 SHCCTO_UNARY_OP(SH_OP_ABS, (shDataTypeIsPositive(*A) ? (*A) : -(*A)));
00165 
00166 SHCCTO_OP_CMATH_SPEC(SH_OP_ACOS);
00167 SHCCTO_OP_CMATH_SPEC(SH_OP_ASIN);
00168 
00169 SHCCTO_UNARY_OP(SH_OP_ASN, (*A));
00170 
00171 SHCCTO_OP_CMATH_SPEC(SH_OP_ATAN);
00172 SHCCTO_OP_CMATH_SPEC(SH_OP_CBRT);
00173 SHCCTO_OP_CMATH_SPEC(SH_OP_CEIL);
00174 
00175 template<typename T>
00176 struct ShConcreteCTypeOp<SH_OP_CMUL, T>
00177 { 
00178   typedef ShDataVariant<T, SH_HOST> Variant; 
00179   typedef Variant* DataPtr; 
00180   typedef const Variant* DataCPtr; 
00181 
00182   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00183   {
00184     // dest->size should be 1 and a->size == b->size
00185     (*dest)[0] = std::accumulate(a->begin(), a->end(), 
00186                      ShDataTypeInfo<T, SH_HOST>::One, 
00187                      std::multiplies<typename Variant::DataType>());
00188   }
00189 };
00190 
00191 SHCCTO_OP_CMATH_SPEC(SH_OP_COS);
00192 
00193 template<typename T>
00194 struct ShConcreteCTypeOp<SH_OP_CSUM, T>
00195 { 
00196   typedef ShDataVariant<T, SH_HOST> Variant; 
00197   typedef Variant* DataPtr; 
00198   typedef const Variant* DataCPtr; 
00199 
00200   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00201   {
00202     // dest->size should be 1 and a->size == b->size
00203     (*dest)[0] = std::accumulate(a->begin(), a->end(), 
00204                      ShDataTypeInfo<T, SH_HOST>::Zero, 
00205                      std::plus<typename Variant::DataType>()); 
00206   }
00207 };
00208 
00209 SHCCTO_OP_CMATH_SPEC(SH_OP_EXP);
00210 SHCCTO_OP_CMATH_SPEC(SH_OP_EXP2);
00211 SHCCTO_OP_CMATH_SPEC(SH_OP_EXP10);
00212 SHCCTO_OP_CMATH_SPEC(SH_OP_FLR);
00213 SHCCTO_OP_CMATH_SPEC(SH_OP_FRAC);
00214 SHCCTO_OP_CMATH_SPEC(SH_OP_LOG);
00215 SHCCTO_OP_CMATH_SPEC(SH_OP_LOG2);
00216 SHCCTO_OP_CMATH_SPEC(SH_OP_LOG10);
00217 SHCCTO_OP_CMATH_SPEC(SH_OP_NORM);
00218 
00219 SHCCTO_UNARY_OP(SH_OP_RCP, 1 / (*A));
00220 
00221 SHCCTO_OP_CMATH_SPEC(SH_OP_RND);
00222 SHCCTO_OP_CMATH_SPEC(SH_OP_RSQ);
00223 SHCCTO_OP_CMATH_SPEC(SH_OP_SIN);
00224 
00225 SHCCTO_UNARY_OP(SH_OP_SGN, (*A) > 0 ? 1 : (*A) < 0 ? -1 : 0); 
00226 
00227 SHCCTO_OP_CMATH_SPEC(SH_OP_SQRT);
00228 SHCCTO_OP_CMATH_SPEC(SH_OP_TAN);
00229 
00230 template<typename T>
00231 struct ShConcreteCTypeOp<SH_OP_LIT, T>
00232 { 
00233   typedef ShDataVariant<T, SH_HOST> Variant; 
00234   typedef Variant* DataPtr; 
00235   typedef const Variant* DataCPtr; 
00236 
00237   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00238   {
00239     typename Variant::DataType x, y, w;
00240     x = (*a)[0];
00241     if (x < 0) x = 0;
00242     y = (*a)[1];
00243     if (y < 0) y = 0;
00244     w = (*a)[2];
00245     if (w < -128) w = -128;
00246     if (w > 128) w = 128;
00247     (*dest)[0] = 1;
00248     (*dest)[1] = x;
00249     (*dest)[2] = (x > 0) ? std::pow(y,w) : 0;
00250     (*dest)[3] = 1;
00251   }
00252 };
00253 
00254 // Binary ops
00255 SHCCTO_BINARY_OP(SH_OP_ADD, (*A) + (*B));
00256 
00257 SHCCTO_OP_CMATH_SPEC(SH_OP_ATAN2);
00258 
00259 SHCCTO_BINARY_OP(SH_OP_DIV, (*A) / (*B));
00260 
00261 template<typename T>
00262 struct ShConcreteCTypeOp<SH_OP_DOT, T>
00263 { 
00264   typedef ShDataVariant<T, SH_HOST> Variant; 
00265   typedef Variant* DataPtr; 
00266   typedef const Variant* DataCPtr; 
00267 
00268   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00269   {
00270     // dest->size should be 1 and a->size == b->size
00271     (*dest)[0] = std::inner_product(a->begin(), a->end(), b->begin(), 
00272                       ShDataTypeInfo<T, SH_HOST>::Zero);
00273   }
00274 };
00275 
00276 SHCCTO_BINARY_OP(SH_OP_MAX, std::max((*A), (*B))); 
00277 SHCCTO_BINARY_OP(SH_OP_MIN, std::min((*A), (*B))); 
00278 
00279 SHCCTO_BINARY_OP(SH_OP_MOD, ((*A) - (*B) * (int)std::floor((double)(*A) / (*B)))); 
00280 SHCCTO_OP_CMATH_SPEC(SH_OP_MOD);
00281 
00282 SHCCTO_BINARY_OP(SH_OP_MUL, (*A) * (*B));
00283 
00284 // TODO implemeng power for win32
00285 SHCCTO_BINARY_OP(SH_OP_POW, _sh_intpow((*A), (*B)));  // only works for integers
00286 SHCCTO_OP_CMATH_SPEC(SH_OP_POW);
00287 
00288 
00289 SHCCTO_BINARY_OP(SH_OP_SEQ, (shDataTypeCond<T, SH_HOST>((*A) == (*B))));
00290 SHCCTO_BINARY_OP(SH_OP_SGE, (shDataTypeCond<T, SH_HOST>((*A) >= (*B))));
00291 SHCCTO_BINARY_OP(SH_OP_SGT, (shDataTypeCond<T, SH_HOST>((*A) > (*B))));
00292 SHCCTO_BINARY_OP(SH_OP_SLE, (shDataTypeCond<T, SH_HOST>((*A) <= (*B))));
00293 SHCCTO_BINARY_OP(SH_OP_SLT, (shDataTypeCond<T, SH_HOST>((*A) < (*B))));
00294 SHCCTO_BINARY_OP(SH_OP_SNE, (shDataTypeCond<T, SH_HOST>((*A) != (*B))));
00295 
00296 template<typename T>
00297 struct ShConcreteCTypeOp<SH_OP_XPD, T>
00298 { 
00299   typedef ShDataVariant<T, SH_HOST> Variant; 
00300   typedef Variant* DataPtr; 
00301   typedef const Variant* DataCPtr; 
00302 
00303   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00304   {
00305     // handle case where dest = a and both not swizzed/negged
00306     // or similar with dest = b.
00307     typename Variant::DataType t0, t1;
00308     t0 = (*a)[1] * (*b)[2] - (*a)[2] * (*b)[1];
00309     t1 = -((*a)[0] * (*b)[2] - (*a)[2] * (*b)[0]);
00310     (*dest)[2] = (*a)[0] * (*b)[1] - (*a)[1] * (*b)[0];
00311     (*dest)[0] = t0;
00312     (*dest)[1] = t1;
00313   }
00314 };
00315 
00316 // Ternary Ops
00317 SHCCTO_TERNARY_OP(SH_OP_COND, ((*A) > 0 ? (*B) : (*C))); 
00318 SHCCTO_TERNARY_OP(SH_OP_LRP, (*A) * (*B) + (1 - (*A)) * (*C)); 
00319 SHCCTO_TERNARY_OP(SH_OP_MAD, (*A) * (*B) + (*C)); 
00320 
00321 }
00322 
00323 #endif

Generated on Thu Apr 21 17:32:46 2005 for Sh by  doxygen 1.4.2