00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #include <cmath>
00028 #include "ShInstructions.hpp"
00029 #include "ShStatement.hpp"
00030 #include "ShContext.hpp"
00031 #include "ShVariant.hpp"
00032 #include "ShEval.hpp"
00033 #include "ShDebug.hpp"
00034 #include "ShError.hpp"
00035
00036 namespace {
00037
00038 using namespace SH;
00039
00040 inline bool immediate()
00041 {
00042 return !ShContext::current()->parsing();
00043 }
00044
00045 inline void sizes_match(const ShVariable& a, const ShVariable& b)
00046 {
00047 SH_DEBUG_ASSERT(a.size() == b.size());
00048 }
00049
00050 inline void sizes_match(const ShVariable& a, const ShVariable& b,
00051 const ShVariable& c, bool scalar_b = false, bool scalar_c = false)
00052 {
00053 SH_DEBUG_ASSERT(((scalar_b && b.size() == 1) || a.size() == b.size()) &&
00054 ((scalar_c && c.size() == 1) || a.size() == c.size()));
00055 }
00056
00057 inline void has_values(const ShVariable& a)
00058 {
00059 SH_DEBUG_ASSERT(a.hasValues());
00060 }
00061
00062 inline void has_values(const ShVariable& a, const ShVariable& b)
00063 {
00064 SH_DEBUG_ASSERT(a.hasValues());
00065 SH_DEBUG_ASSERT(b.hasValues());
00066 }
00067
00068 inline void has_values(const ShVariable& a, const ShVariable& b, const ShVariable& c)
00069 {
00070 SH_DEBUG_ASSERT(a.hasValues());
00071 SH_DEBUG_ASSERT(b.hasValues());
00072 SH_DEBUG_ASSERT(c.hasValues());
00073 }
00074
00075 inline void has_values(const ShVariable& a, const ShVariable& b,
00076 const ShVariable& c, const ShVariable& d)
00077 {
00078 SH_DEBUG_ASSERT(a.hasValues());
00079 SH_DEBUG_ASSERT(b.hasValues());
00080 SH_DEBUG_ASSERT(c.hasValues());
00081 SH_DEBUG_ASSERT(d.hasValues());
00082 }
00083
00084 inline void addStatement(const ShStatement& stmt)
00085 {
00086 ShContext::current()->parsing()->tokenizer.blockList()->addStatement(stmt);
00087 }
00088
00089 }
00090
00091 namespace SH {
00092 #define SHINST_UNARY_OP_CORE(op)\
00093 if(immediate()) {\
00094 has_values(dest, src);\
00095 ShVariant *dv, *sv;\
00096 bool newd, news;\
00097 newd = dest.loadVariant(dv);\
00098 news = src.loadVariant(sv);\
00099 (*ShEval::instance())(SH_OP_ ## op, dv, sv, 0, 0);\
00100 if(newd) {\
00101 dest.setVariant(dv); \
00102 delete dv;\
00103 } else {\
00104 dest.updateVariant();\
00105 }\
00106 if(news) delete sv;\
00107 } else {\
00108 ShStatement stmt(dest, SH_OP_ ## op, src);\
00109 addStatement(stmt);\
00110 }
00111
00112 #define SHINST_UNARY_OP(op)\
00113 void sh ## op(ShVariable& dest, const ShVariable& src)\
00114 {\
00115 sizes_match(dest, src);\
00116 SHINST_UNARY_OP_CORE(op);\
00117 }
00118
00119 #define SHINST_BINARY_OP_CORE(op)\
00120 if(immediate()) {\
00121 has_values(dest, a, b);\
00122 ShVariant *dv, *av, *bv;\
00123 bool newd, newa, newb;\
00124 newd = dest.loadVariant(dv);\
00125 newa = a.loadVariant(av);\
00126 newb = b.loadVariant(bv);\
00127 (*ShEval::instance())(SH_OP_ ## op, dv, av, bv, 0);\
00128 if(newd) {\
00129 dest.setVariant(dv); \
00130 delete dv;\
00131 } else {\
00132 dest.updateVariant();\
00133 }\
00134 if(newa) delete av;\
00135 if(newb) delete bv;\
00136 } else {\
00137 ShStatement stmt(dest, a, SH_OP_ ## op, b);\
00138 addStatement(stmt);\
00139 }\
00140
00141 #define SHINST_BINARY_OP(op, scalar_a, scalar_b)\
00142 void sh ## op(ShVariable& dest, const ShVariable& a, const ShVariable &b)\
00143 {\
00144 sizes_match(dest, a, b, scalar_a, scalar_b);\
00145 SHINST_BINARY_OP_CORE(op);\
00146 }
00147
00148
00149 #define SHINST_TERNARY_OP(op, condition)\
00150 void sh ## op(ShVariable& dest, const ShVariable& a, const ShVariable &b, const ShVariable &c)\
00151 {\
00152 SH_DEBUG_ASSERT(condition);\
00153 if(immediate()) {\
00154 has_values(dest, a, b, c);\
00155 ShVariant *dv, *av, *bv, *cv;\
00156 bool newd, newa, newb, newc;\
00157 newd = dest.loadVariant(dv);\
00158 newa = a.loadVariant(av);\
00159 newb = b.loadVariant(bv);\
00160 newc = c.loadVariant(cv);\
00161 (*ShEval::instance())(SH_OP_ ## op, dv, av, bv, cv);\
00162 if(newd) {\
00163 dest.setVariant(dv); \
00164 delete dv;\
00165 } else {\
00166 dest.updateVariant();\
00167 }\
00168 if(newa) delete av;\
00169 if(newb) delete bv;\
00170 if(newc) delete cv;\
00171 } else {\
00172 ShStatement stmt(dest, SH_OP_ ## op, a, b, c);\
00173 addStatement(stmt);\
00174 }\
00175 }
00176
00177
00178
00179
00180
00181
00182 SHINST_UNARY_OP(ASN);
00183
00184 SHINST_BINARY_OP(ADD, true, true);
00185 SHINST_BINARY_OP(MUL, true, true);
00186 SHINST_BINARY_OP(DIV, true, true);
00187 SHINST_BINARY_OP(SLT, true, true);
00188 SHINST_BINARY_OP(SLE, true, true);
00189 SHINST_BINARY_OP(SGT, true, true);
00190 SHINST_BINARY_OP(SGE, true, true);
00191 SHINST_BINARY_OP(SEQ, true, true);
00192 SHINST_BINARY_OP(SNE, true, true);
00193
00194 SHINST_UNARY_OP(ABS);
00195 SHINST_UNARY_OP(ACOS);
00196 SHINST_UNARY_OP(ASIN);
00197 SHINST_UNARY_OP(ATAN);
00198 SHINST_BINARY_OP(ATAN2, false, false);
00199 SHINST_UNARY_OP(CBRT);
00200 SHINST_UNARY_OP(CEIL);
00201 SHINST_UNARY_OP(COS);
00202
00203 void shCMUL(ShVariable& dest, const ShVariable& src)
00204 {
00205 SH_DEBUG_ASSERT(dest.size() == 1);
00206 SHINST_UNARY_OP_CORE(CMUL);
00207 }
00208
00209 void shCSUM(ShVariable& dest, const ShVariable& src)
00210 {
00211 SH_DEBUG_ASSERT(dest.size() == 1);
00212 SHINST_UNARY_OP_CORE(CSUM);
00213 }
00214
00215 void shDOT(ShVariable& dest, const ShVariable& a, const ShVariable& b)
00216 {
00217 SH_DEBUG_ASSERT(dest.size() == 1);
00218 sizes_match(a, b);
00219 SHINST_BINARY_OP_CORE(DOT);
00220 }
00221
00222 void shDX(ShVariable &dest, const ShVariable& a)
00223 {
00224 if(immediate()) {
00225 shError(ShScopeException("Cannot take derivatives in immediate mode"));
00226 }
00227 ShStatement stmt(dest, SH_OP_DX, a);
00228 addStatement(stmt);
00229 }
00230
00231 void shDY(ShVariable &dest, const ShVariable& a)
00232 {
00233 if(immediate()) {
00234 shError(ShScopeException("Cannot take derivatives in immediate mode"));
00235 }
00236 SH_DEBUG_ASSERT(!immediate());
00237 ShStatement stmt(dest, SH_OP_DY, a);
00238 addStatement(stmt);
00239 }
00240
00241 SHINST_UNARY_OP(EXP);
00242 SHINST_UNARY_OP(EXP2);
00243 SHINST_UNARY_OP(EXP10);
00244 SHINST_UNARY_OP(FLR);
00245 SHINST_BINARY_OP(MOD, false, false);
00246 SHINST_UNARY_OP(FRAC);
00247 SHINST_TERNARY_OP(LRP,
00248 (dest.size() == b.size() &&
00249 dest.size() == c.size() &&
00250 (dest.size() == a.size() || a.size() == 1)));
00251
00252 SHINST_UNARY_OP(LOG);
00253 SHINST_UNARY_OP(LOG2);
00254 SHINST_UNARY_OP(LOG10);
00255
00256 SHINST_TERNARY_OP(MAD,
00257 (dest.size() == c.size() &&
00258 (dest.size() == a.size() || (dest.size() == b.size() && a.size() == 1)) &&
00259 (dest.size() == b.size() || (dest.size() == a.size() && b.size() == 1))));
00260
00261 SHINST_BINARY_OP(MAX, false, false);
00262 SHINST_BINARY_OP(MIN, false, false);
00263 SHINST_BINARY_OP(POW, false, true);
00264 SHINST_UNARY_OP(RCP);
00265 SHINST_UNARY_OP(RND);
00266 SHINST_UNARY_OP(RSQ);
00267 SHINST_UNARY_OP(SGN);
00268 SHINST_UNARY_OP(SIN);
00269 SHINST_UNARY_OP(SQRT);
00270 SHINST_UNARY_OP(TAN);
00271 SHINST_UNARY_OP(NORM);
00272
00273
00274 void shXPD(ShVariable& dest, const ShVariable& a, const ShVariable& b)
00275 {
00276 SH_DEBUG_ASSERT(dest.size() == 3 && a.size() == 3 && b.size() == 3);
00277 SHINST_BINARY_OP_CORE(XPD);
00278 }
00279
00280 SHINST_TERNARY_OP(COND,
00281 (dest.size() == b.size() &&
00282 dest.size() == c.size() &&
00283 (dest.size() == a.size() || a.size() == 1)));
00284
00285 void shLO(ShVariable& dest, const ShVariable& src)
00286 {
00287 sizes_match(dest, src);
00288 SHINST_UNARY_OP_CORE(LO);
00289 }
00290
00291 void shHI(ShVariable& dest, const ShVariable& src)
00292 {
00293 sizes_match(dest, src);
00294 SHINST_UNARY_OP_CORE(HI);
00295 }
00296
00297 void shSETLO(ShVariable& dest, const ShVariable& src)
00298 {
00299 sizes_match(dest, src);
00300 SHINST_UNARY_OP_CORE(SETLO);
00301 }
00302
00303 void shSETHI(ShVariable& dest, const ShVariable& src)
00304 {
00305 sizes_match(dest, src);
00306 SHINST_UNARY_OP_CORE(SETHI);
00307 }
00308
00309 void shKIL(const ShVariable& a)
00310 {
00311 if(immediate()) {
00312 shError(ShScopeException("Cannot kill in immediate mode"));
00313 }
00314 SH_DEBUG_ASSERT(!immediate());
00315 ShStatement stmt(a, SH_OP_KIL, a);
00316 addStatement(stmt);
00317 }
00318
00319 }