ShConcreteCTypeOpImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2006 Serious Hack Inc.
00004 // 
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00018 // MA  02110-1301, USA
00020 #ifndef SHCONCRETECTYPEOPIMPL_HPP 
00021 #define SHCONCRETECTYPEOPIMPL_HPP
00022 
00023 #include <numeric>
00024 #include <cmath>
00025 #include "ShEval.hpp"
00026 #include "ShVariant.hpp"
00027 #include "ShDebug.hpp"
00028 #include "ShError.hpp"
00029 #include "ShTypeInfo.hpp"
00030 
00031 namespace {
00033 template<typename T1, typename T2>
00034 T1 _sh_intpow(T1 x, T2 pow)
00035 {
00036   T1 result = 1;
00037   if (pow < 0) { 
00038     x = 1 / x;
00039     pow = -pow;
00040   }
00041   for (;pow; pow >>= 1, x *= x) {
00042     if (pow & 1) result *= x;
00043   }
00044   return result;
00045 }
00046 }
00047 
00048 namespace SH {
00049 
00050 /* Partial specialization for different operations */ 
00051 
00052 /* The operators that depend on cmath different library functions
00053  * are specialized for float and double types in ShEval.cpp 
00054  * right now
00055  */
00056 // TODO make this cleaner?
00057 
00058 // TODO use the information from sdt's ShOperationInfo to decide
00059 // whether to do the ao/bo/co = 0 special case for scalar
00060 // ops where we step through the destination tuple but always
00061 // use the same element from the scalar src tuple. 
00062 
00063 // macros for componentwise operations
00064 // do a partial specialization on the class
00065 // and define the doop function
00066 #define SHCCTO_UNARY_OP(op, opsrc)\
00067 template<typename T>\
00068 struct ShConcreteCTypeOp<op, T>\
00069 { \
00070   typedef ShDataVariant<T, SH_HOST> Variant; \
00071   typedef Variant* DataPtr; \
00072   typedef const Variant* DataCPtr; \
00073 \
00074   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00075   {\
00076     SH_DEBUG_ASSERT(dest && a);\
00077     int ao = a->size() > 1;\
00078   \
00079     typename Variant::iterator D = dest->begin();\
00080     typename Variant::const_iterator A = a->begin();\
00081     for(; D != dest->end(); A += ao, ++D) {\
00082       (*D) = opsrc;\
00083     }\
00084   } \
00085 };
00086 
00087 
00088 #define SHCCTO_BINARY_OP(op, opsrc)\
00089 template<typename T>\
00090 struct ShConcreteCTypeOp<op, T>\
00091 { \
00092   typedef ShDataVariant<T, SH_HOST> Variant; \
00093   typedef Variant* DataPtr; \
00094   typedef const Variant* DataCPtr; \
00095 \
00096   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00097   {\
00098     SH_DEBUG_ASSERT(dest && a && b);\
00099     int ao = a->size() > 1;\
00100     int bo = b->size() > 1;\
00101   \
00102     typename Variant::iterator D = dest->begin();\
00103     typename Variant::const_iterator A, B;\
00104     A = a->begin();\
00105     B = b->begin();\
00106     for(; D != dest->end(); A += ao, B += bo, ++D) {\
00107       (*D) = opsrc;\
00108     }\
00109   } \
00110 };
00111 
00112 
00113 #define SHCCTO_TERNARY_OP(op, opsrc)\
00114 template<typename T>\
00115 struct ShConcreteCTypeOp<op, T>\
00116 { \
00117   typedef ShDataVariant<T, SH_HOST> Variant; \
00118   typedef Variant* DataPtr; \
00119   typedef const Variant* DataCPtr; \
00120 \
00121   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) \
00122   {\
00123     SH_DEBUG_ASSERT(dest && a && b && c);\
00124     int ao = a->size() > 1;\
00125     int bo = b->size() > 1;\
00126     int co = c->size() > 1;\
00127   \
00128     typename Variant::iterator D = dest->begin();\
00129     typename Variant::const_iterator A, B, C;\
00130     A = a->begin();\
00131     B = b->begin();\
00132     C = c->begin();\
00133     for(; D != dest->end(); A += ao, B += bo, C += co, ++D) {\
00134       (*D) = opsrc;\
00135     }\
00136   }\
00137 };
00138 
00139 #define SHCCTO_OP_SPEC(T, op)\
00140 template<>\
00141 struct  \
00142 SH_DLLEXPORT \
00143 ShConcreteCTypeOp<op, T>\
00144 { \
00145   typedef ShDataVariant<T, SH_HOST> Variant; \
00146   typedef Variant* DataPtr; \
00147   typedef const Variant* DataCPtr; \
00148 \
00149   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0); \
00150 };
00151 
00152 #define SHCCTO_OP_CMATH_SPEC(op)\
00153   SHCCTO_OP_SPEC(double, op);\
00154   SHCCTO_OP_SPEC(float, op);
00155 
00156 // Note that some ops are currently NOT declared for integer types
00157 // (anything that is only specialized for double/float cmath functions 
00158 // will not work with ints)
00159 
00160 // Unary ops
00161 SHCCTO_UNARY_OP(SH_OP_ABS, (shDataTypeIsPositive(*A) ? (*A) : -(*A)));
00162 
00163 SHCCTO_OP_CMATH_SPEC(SH_OP_ACOS);
00164 SHCCTO_OP_CMATH_SPEC(SH_OP_ACOSH);
00165 SHCCTO_OP_CMATH_SPEC(SH_OP_ASIN);
00166 SHCCTO_OP_CMATH_SPEC(SH_OP_ASINH);
00167 
00168 SHCCTO_UNARY_OP(SH_OP_ASN, (*A));
00169 
00170 SHCCTO_OP_CMATH_SPEC(SH_OP_ATAN);
00171 SHCCTO_OP_CMATH_SPEC(SH_OP_ATANH);
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 template<typename T>
00255 struct ShConcreteCTypeOp<SH_OP_HASH, T>
00256 {
00257   typedef ShDataVariant<T, SH_HOST> Variant; 
00258   typedef Variant* DataPtr; 
00259   typedef const Variant* DataCPtr; 
00260 
00261   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00262   {
00263     SH_DEBUG_ASSERT(dest && a);
00264     typename Variant::iterator D = dest->begin();
00265     typename Variant::const_iterator A = a->begin();
00266     for(; D != dest->end(); ++A, ++D) (*D) = (*A);
00267     // TODO: implement the real algorithm
00268   }
00269 };
00270 
00271 template<typename T>
00272 struct ShConcreteCTypeOp<SH_OP_NOISE, T>
00273 {
00274   typedef ShDataVariant<T, SH_HOST> Variant; 
00275   typedef Variant* DataPtr; 
00276   typedef const Variant* DataCPtr; 
00277 
00278   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00279   {
00280     SH_DEBUG_ASSERT(dest && a);
00281     typename Variant::iterator D = dest->begin();
00282     typename Variant::const_iterator A = a->begin();
00283     for(; D != dest->end(); ++A, ++D) (*D) = (*A);
00284     // TODO: implement the real algorithm
00285   }
00286 };
00287 
00288 // Binary ops
00289 SHCCTO_BINARY_OP(SH_OP_ADD, (*A) + (*B));
00290 
00291 SHCCTO_OP_CMATH_SPEC(SH_OP_ATAN2);
00292 
00293 SHCCTO_BINARY_OP(SH_OP_DIV, (*A) / (*B));
00294 
00295 template<typename T>
00296 struct ShConcreteCTypeOp<SH_OP_DOT, T>
00297 { 
00298   typedef ShDataVariant<T, SH_HOST> Variant; 
00299   typedef Variant* DataPtr; 
00300   typedef const Variant* DataCPtr; 
00301 
00302   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00303   {
00304     // dest->size should be 1 and a->size == b->size
00305     (*dest)[0] = std::inner_product(a->begin(), a->end(), b->begin(), 
00306                       ShDataTypeInfo<T, SH_HOST>::Zero);
00307   }
00308 };
00309 
00310 SHCCTO_BINARY_OP(SH_OP_MAX, std::max((*A), (*B))); 
00311 SHCCTO_BINARY_OP(SH_OP_MIN, std::min((*A), (*B))); 
00312 
00313 SHCCTO_BINARY_OP(SH_OP_MOD, ((*A) - (*B) * (int)std::floor((double)(*A) / (*B)))); 
00314 SHCCTO_OP_CMATH_SPEC(SH_OP_MOD);
00315 
00316 SHCCTO_BINARY_OP(SH_OP_MUL, (*A) * (*B));
00317 
00318 // TODO implemeng power for win32
00319 SHCCTO_BINARY_OP(SH_OP_POW, _sh_intpow((*A), (*B)));  // only works for integers
00320 SHCCTO_OP_CMATH_SPEC(SH_OP_POW);
00321 
00322 
00323 SHCCTO_BINARY_OP(SH_OP_SEQ, (shDataTypeCond<T, SH_HOST>((*A) == (*B))));
00324 SHCCTO_BINARY_OP(SH_OP_SGE, (shDataTypeCond<T, SH_HOST>((*A) >= (*B))));
00325 SHCCTO_BINARY_OP(SH_OP_SGT, (shDataTypeCond<T, SH_HOST>((*A) > (*B))));
00326 SHCCTO_BINARY_OP(SH_OP_SLE, (shDataTypeCond<T, SH_HOST>((*A) <= (*B))));
00327 SHCCTO_BINARY_OP(SH_OP_SLT, (shDataTypeCond<T, SH_HOST>((*A) < (*B))));
00328 SHCCTO_BINARY_OP(SH_OP_SNE, (shDataTypeCond<T, SH_HOST>((*A) != (*B))));
00329 
00330 template<typename T>
00331 struct ShConcreteCTypeOp<SH_OP_XPD, T>
00332 { 
00333   typedef ShDataVariant<T, SH_HOST> Variant; 
00334   typedef Variant* DataPtr; 
00335   typedef const Variant* DataCPtr; 
00336 
00337   static void doop(DataPtr dest, DataCPtr a, DataCPtr b = 0, DataCPtr c = 0) 
00338   {
00339     // handle case where dest = a and both not swizzed/negged
00340     // or similar with dest = b.
00341     typename Variant::DataType t0, t1;
00342     t0 = (*a)[1] * (*b)[2] - (*a)[2] * (*b)[1];
00343     t1 = -((*a)[0] * (*b)[2] - (*a)[2] * (*b)[0]);
00344     (*dest)[2] = (*a)[0] * (*b)[1] - (*a)[1] * (*b)[0];
00345     (*dest)[0] = t0;
00346     (*dest)[1] = t1;
00347   }
00348 };
00349 
00350 // Ternary Ops
00351 SHCCTO_TERNARY_OP(SH_OP_COND, ((*A) > 0 ? (*B) : (*C))); 
00352 SHCCTO_TERNARY_OP(SH_OP_LRP, (*A) * (*B) + (1 - (*A)) * (*C)); 
00353 SHCCTO_TERNARY_OP(SH_OP_MAD, (*A) * (*B) + (*C)); 
00354 
00355 }
00356 
00357 #endif

Generated on Thu Feb 16 14:51:31 2006 for Sh by  doxygen 1.4.6