00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
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
00157
00158
00159
00160
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
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
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
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
00285 }
00286 };
00287
00288
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
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
00319 SHCCTO_BINARY_OP(SH_OP_POW, _sh_intpow((*A), (*B)));
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
00340
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
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