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 #ifndef SHCONCRETECTYPEOPIMPL_HPP 
00002 #define SHCONCRETECTYPEOPIMPL_HPP
00003 
00004 #include <numeric>
00005 #include "ShEval.hpp"
00006 #include "ShVariant.hpp"
00007 #include "ShDebug.hpp"
00008 #include "ShError.hpp"
00009 #include "ShTypeInfo.hpp"
00010 
00011 namespace {
00013 template<typename T1, typename T2>
00014 T1 _sh_intpow(T1 x, T2 pow)
00015 {
00016         T1 result = 1;
00017         if(pow < 0) { 
00018                 x = 1 / x;
00019                 pow = -pow;
00020         }
00021         for(;pow; pow >>= 1, x *= x) {
00022                 if(pow & 1) result *= x;
00023         }
00024         return result;
00025 }
00026 }
00027 namespace SH {
00028 
00029 /* Partial specialization for different operations */ 
00030 
00031 /* The operators that depend on cmath different library functions
00032  * are specialized for float and double types in ShEval.cpp 
00033  * right now
00034  */
00035 // TODO make this cleaner?
00036 
00037 // TODO use the information from sdt's ShOperationInfo to decide
00038 // whether to do the ao/bo/co = 0 special case for scalar
00039 // ops where we step through the destination tuple but always
00040 // use the same element from the scalar src tuple. 
00041 
00042 // macros for componentwise operations
00043 // do a partial specialization on the class
00044 // and define the doop function
00045 #define SHCCTO_UNARY_OP(op, opsrc)\
00046 template<typename T>\
00047 struct ShConcreteCTypeOp<op, T>\
00048 { \
00049   typedef ShDataVariant<T, SH_HOST> Variant; \
00050   typedef Variant* DataPtr; \
00051   typedef const Variant* DataCPtr; \
00052 \
00053   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00054   {\
00055     SH_DEBUG_ASSERT(dest && a);\
00056     int ao = a->size() > 1;\
00057   \
00058     typename Variant::iterator D = dest->begin();\
00059     typename Variant::const_iterator A = a->begin();\
00060     for(; D != dest->end(); A += ao, ++D) {\
00061       (*D) = opsrc;\
00062     }\
00063   } \
00064 };
00065 
00066 
00067 #define SHCCTO_BINARY_OP(op, opsrc)\
00068 template<typename T>\
00069 struct ShConcreteCTypeOp<op, T>\
00070 { \
00071   typedef ShDataVariant<T, SH_HOST> Variant; \
00072   typedef Variant* DataPtr; \
00073   typedef const Variant* DataCPtr; \
00074 \
00075   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00076   {\
00077     SH_DEBUG_ASSERT(dest && a && b);\
00078     int ao = a->size() > 1;\
00079     int bo = b->size() > 1;\
00080   \
00081     typename Variant::iterator D = dest->begin();\
00082     typename Variant::const_iterator A, B;\
00083     A = a->begin();\
00084     B = b->begin();\
00085     for(; D != dest->end(); A += ao, B += bo, ++D) {\
00086       (*D) = opsrc;\
00087     }\
00088   } \
00089 };
00090 
00091 
00092 #define SHCCTO_TERNARY_OP(op, opsrc)\
00093 template<typename T>\
00094 struct ShConcreteCTypeOp<op, T>\
00095 { \
00096   typedef ShDataVariant<T, SH_HOST> Variant; \
00097   typedef Variant* DataPtr; \
00098   typedef const Variant* DataCPtr; \
00099 \
00100   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00101   {\
00102     SH_DEBUG_ASSERT(dest && a && b && c);\
00103     int ao = a->size() > 1;\
00104     int bo = b->size() > 1;\
00105     int co = c->size() > 1;\
00106   \
00107     typename Variant::iterator D = dest->begin();\
00108     typename Variant::const_iterator A, B, C;\
00109     A = a->begin();\
00110     B = b->begin();\
00111     C = c->begin();\
00112     for(; D != dest->end(); A += ao, B += bo, C += co, ++D) {\
00113       (*D) = opsrc;\
00114     }\
00115   }\
00116 };
00117 
00118 #define SHCCTO_OP_SPEC(T, op)\
00119 template<>\
00120 struct  \
00121 SH_DLLEXPORT \
00122 ShConcreteCTypeOp<op, T>\
00123 { \
00124   typedef ShDataVariant<T, SH_HOST> Variant; \
00125   typedef Variant* DataPtr; \
00126   typedef const Variant* DataCPtr; \
00127 \
00128   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0); \
00129 };
00130 
00131 #define SHCCTO_OP_CMATH_SPEC(op)\
00132   SHCCTO_OP_SPEC(double, op);\
00133   SHCCTO_OP_SPEC(float, op);
00134 
00135 // Note that some ops are currently NOT declared for integer types
00136 // (anything that is only specialized for double/float cmath functions 
00137 // will not work with ints)
00138 
00139 // Unary ops
00140 SHCCTO_UNARY_OP(SH_OP_ABS, (shDataTypeIsPositive(*A) ? (*A) : -(*A)));
00141 
00142 SHCCTO_OP_CMATH_SPEC(SH_OP_ACOS);
00143 SHCCTO_OP_CMATH_SPEC(SH_OP_ASIN);
00144 
00145 SHCCTO_UNARY_OP(SH_OP_ASN, (*A));
00146 
00147 SHCCTO_OP_CMATH_SPEC(SH_OP_ATAN);
00148 SHCCTO_OP_CMATH_SPEC(SH_OP_CBRT);
00149 SHCCTO_OP_CMATH_SPEC(SH_OP_CEIL);
00150 
00151 template<typename T>
00152 struct ShConcreteCTypeOp<SH_OP_CMUL, T>
00153 { 
00154   typedef ShDataVariant<T, SH_HOST> Variant; 
00155   typedef Variant* DataPtr; 
00156   typedef const Variant* DataCPtr; 
00157 
00158   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00159   {
00160     // dest->size should be 1 and a->size == b->size
00161     (*dest)[0] = std::accumulate(a->begin(), a->end(), 
00162                      ShDataTypeInfo<T, SH_HOST>::Zero, 
00163                      std::multiplies<typename Variant::DataType>());
00164   }
00165 };
00166 
00167 SHCCTO_OP_CMATH_SPEC(SH_OP_COS);
00168 
00169 template<typename T>
00170 struct ShConcreteCTypeOp<SH_OP_CSUM, T>
00171 { 
00172   typedef ShDataVariant<T, SH_HOST> Variant; 
00173   typedef Variant* DataPtr; 
00174   typedef const Variant* DataCPtr; 
00175 
00176   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00177   {
00178     // dest->size should be 1 and a->size == b->size
00179     (*dest)[0] = std::accumulate(a->begin(), a->end(), 
00180                      ShDataTypeInfo<T, SH_HOST>::Zero, 
00181                      std::plus<typename Variant::DataType>()); 
00182   }
00183 };
00184 
00185 SHCCTO_OP_CMATH_SPEC(SH_OP_EXP);
00186 SHCCTO_OP_CMATH_SPEC(SH_OP_EXP2);
00187 SHCCTO_OP_CMATH_SPEC(SH_OP_EXP10);
00188 SHCCTO_OP_CMATH_SPEC(SH_OP_FLR);
00189 SHCCTO_OP_CMATH_SPEC(SH_OP_FRAC);
00190 SHCCTO_OP_CMATH_SPEC(SH_OP_LOG);
00191 SHCCTO_OP_CMATH_SPEC(SH_OP_LOG2);
00192 SHCCTO_OP_CMATH_SPEC(SH_OP_LOG10);
00193 SHCCTO_OP_CMATH_SPEC(SH_OP_NORM);
00194 
00195 SHCCTO_UNARY_OP(SH_OP_RCP, 1 / (*A));
00196 
00197 SHCCTO_OP_CMATH_SPEC(SH_OP_RND);
00198 SHCCTO_OP_CMATH_SPEC(SH_OP_RSQ);
00199 SHCCTO_OP_CMATH_SPEC(SH_OP_SIN);
00200 
00201 SHCCTO_UNARY_OP(SH_OP_SGN, (*A) > 0 ? 1 : (*A) < 0 ? -1 : 0); 
00202 
00203 SHCCTO_OP_CMATH_SPEC(SH_OP_SQRT);
00204 SHCCTO_OP_CMATH_SPEC(SH_OP_TAN);
00205 
00206 
00207 // Binary ops
00208 SHCCTO_BINARY_OP(SH_OP_ADD, (*A) + (*B));
00209 
00210 SHCCTO_OP_CMATH_SPEC(SH_OP_ATAN2);
00211 
00212 SHCCTO_BINARY_OP(SH_OP_DIV, (*A) / (*B));
00213 
00214 template<typename T>
00215 struct ShConcreteCTypeOp<SH_OP_DOT, T>
00216 { 
00217   typedef ShDataVariant<T, SH_HOST> Variant; 
00218   typedef Variant* DataPtr; 
00219   typedef const Variant* DataCPtr; 
00220 
00221   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00222   {
00223     // dest->size should be 1 and a->size == b->size
00224     (*dest)[0] = std::inner_product(a->begin(), a->end(), b->begin(), 
00225                       ShDataTypeInfo<T, SH_HOST>::Zero);
00226   }
00227 };
00228 
00229 SHCCTO_BINARY_OP(SH_OP_MAX, std::max((*A), (*B))); 
00230 SHCCTO_BINARY_OP(SH_OP_MIN, std::min((*A), (*B))); 
00231 
00232 SHCCTO_BINARY_OP(SH_OP_MOD, (*A) % (*B)); 
00233 SHCCTO_OP_CMATH_SPEC(SH_OP_MOD);
00234 
00235 SHCCTO_BINARY_OP(SH_OP_MUL, (*A) * (*B));
00236 
00237 // TODO implemeng power for win32
00238 SHCCTO_BINARY_OP(SH_OP_POW, _sh_intpow((*A), (*B)));  // only works for integers
00239 SHCCTO_OP_CMATH_SPEC(SH_OP_POW);
00240 
00241 
00242 SHCCTO_BINARY_OP(SH_OP_SEQ, (shDataTypeCond<T, SH_HOST>((*A) == (*B))));
00243 SHCCTO_BINARY_OP(SH_OP_SGE, (shDataTypeCond<T, SH_HOST>((*A) >= (*B))));
00244 SHCCTO_BINARY_OP(SH_OP_SGT, (shDataTypeCond<T, SH_HOST>((*A) > (*B))));
00245 SHCCTO_BINARY_OP(SH_OP_SLE, (shDataTypeCond<T, SH_HOST>((*A) <= (*B))));
00246 SHCCTO_BINARY_OP(SH_OP_SLT, (shDataTypeCond<T, SH_HOST>((*A) < (*B))));
00247 SHCCTO_BINARY_OP(SH_OP_SNE, (shDataTypeCond<T, SH_HOST>((*A) != (*B))));
00248 
00249 template<typename T>
00250 struct ShConcreteCTypeOp<SH_OP_XPD, T>
00251 { 
00252   typedef ShDataVariant<T, SH_HOST> Variant; 
00253   typedef Variant* DataPtr; 
00254   typedef const Variant* DataCPtr; 
00255 
00256   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00257   {
00258     // handle case where dest = a and both not swizzed/negged
00259     // or similar with dest = b.
00260     typename Variant::DataType t0, t1;
00261     t0 = (*a)[1] * (*b)[2] - (*a)[2] * (*b)[1];
00262     t1 = -((*a)[0] * (*b)[2] - (*a)[2] * (*b)[0]);
00263     (*dest)[2] = (*a)[0] * (*b)[1] - (*a)[1] * (*b)[0];
00264     (*dest)[0] = t0;
00265     (*dest)[1] = t1;
00266   }
00267 };
00268 
00269 // Ternary Ops
00270 SHCCTO_TERNARY_OP(SH_OP_COND, ((*A) > 0 ? (*B) : (*C))); 
00271 SHCCTO_TERNARY_OP(SH_OP_LRP, (*A) * (*B) + (1 - (*A)) * (*C)); 
00272 SHCCTO_TERNARY_OP(SH_OP_MAD, (*A) * (*B) + (*C)); 
00273 
00274 
00275 }
00276 
00277 #endif

Generated on Mon Jan 24 18:36:31 2005 for Sh by  doxygen 1.4.1