33 double* fp =
d.data();
34 char** str =
s.data();
41 block->
d.resize(
d.size());
43 memcpy(fp,
d.data(),
d.size() *
sizeof(
double));
46 block->
s.resize(
s.size());
47 str = block->
s.data();
48 memcpy(str,
s.data(),
s.size() *
sizeof(
char*));
52 str[0] =
reinterpret_cast<char*
>(block->
data());
53 str[1] =
reinterpret_cast<char*
>(
static_cast<size_t>(block->
indirectIndex));
57 int end =
static_cast<int>(
ops.size());
60 std::cerr <<
"Running op at " << pc << std::endl;
63 const std::pair<OpF, int>& op =
ops[pc];
64 int* opCurr = &
opData[0] + op.second;
65 pc += op.first(opCurr, fp, str,
callStack);
70 std::cerr <<
"---- ops ----------------------" << std::endl;
71 for (
size_t i = 0; i <
ops.size(); i++) {
72 const char* name =
"";
75 if (dladdr((
void*)
ops[i].first, &info)) name = info.dli_sname;
77 fprintf(stderr,
"%s %s %p (", pc == (
int)i ?
"-->" :
" ", name,
ops[i].first);
78 int nextGuy = (i ==
ops.size() - 1 ?
static_cast<int>(
opData.size()) :
ops[i + 1].second);
79 for (
int k =
ops[i].second; k < nextGuy; k++) {
80 fprintf(stderr,
" %d",
opData[k]);
82 fprintf(stderr,
")\n");
84 std::cerr <<
"---- opdata ----------------------" << std::endl;
85 for (
size_t k = 0; k <
opData.size(); k++) {
86 std::cerr <<
"opData[" << k <<
"]= " <<
opData[k] << std::endl;
89 std::cerr <<
"----- fp --------------------------" << std::endl;
90 for (
size_t k = 0; k <
d.size(); k++) {
91 std::cerr <<
"fp[" << k <<
"]= " <<
d[k] << std::endl;
94 std::cerr <<
"---- str ----------------------" << std::endl;
95 std::cerr <<
"s[0] reserved for datablock = " <<
reinterpret_cast<size_t>(
s[0]) << std::endl;
96 std::cerr <<
"s[1] is indirectIndex = " <<
reinterpret_cast<size_t>(
s[1]) << std::endl;
97 for (
size_t k = 2; k <
s.size(); k++) {
98 std::cerr <<
"s[" << k <<
"]= 0x" <<
s[k];
99 if (
s[k]) std::cerr <<
" '" <<
s[k][0] <<
s[k][1] <<
s[k][2] <<
s[k][3] <<
"...'";
100 std::cerr << std::endl;
110template <
char c,
template <
char c1,
int d>
class T>
146 assert(
false &&
"Invalid dynamic parameter (not supported template)");
155struct BinaryStringOp {
156 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
158 char*& out = *(
char**)c[opData[0]];
159 char* in1 = c[opData[1]];
160 char* in2 = c[opData[2]];
165 int len1 =
static_cast<int>(strlen(in1));
166 int len2 =
static_cast<int>(strlen(in2));
167 if (out == 0 || len1 + len2 + 1 > strlen(out))
170 out =
new char [len1 + len2 + 1];
174 memset(out, 0, len1 + len2 + 1);
178 strcat(out + len1, in2);
179 out[len1 + len2] =
'\0';
189template <
char op,
int d>
191 static double niceMod(
double a,
double b) {
192 if (b == 0)
return 0;
193 return a - floor(a / b) *
b;
196 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
197 double* in1 = fp + opData[0];
198 double* in2 = fp + opData[1];
199 double* out = fp + opData[2];
201 for (
int k = 0; k < d; k++) {
204 *out = (*in1) + (*in2);
207 *out = (*in1) - (*in2);
210 *out = (*in1) * (*in2);
213 *out = (*in1) / (*in2);
216 *out = niceMod(*in1, *in2);
219 *out =
pow(*in1, *in2);
223 *out = (*in1) < (*in2);
226 *out = (*in1) > (*in2);
229 *out = (*in1) <= (*in2);
232 *out = (*in1) >= (*in2);
235 *out = (*in1) && (*in2);
238 *out = (*in1) || (*in2);
252template <
char op,
int d>
254 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
255 double* in = fp + opData[0];
256 double* out = fp + opData[1];
257 for (
int k = 0; k < d; k++) {
281 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
282 int tuple = opData[0];
283 int subscript = int(fp[opData[1]]);
285 if (subscript >= d || subscript < 0)
288 fp[out] = fp[tuple + subscript];
296 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
298 for (
int k = 0; k < d; k++) {
299 fp[out + k] = fp[opData[k]];
308 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
311 for (
int k = 0; k < d; k++) {
312 fp[out + k] = fp[in + k];
320 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
329struct CondJmpRelativeIfFalse {
330 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
331 bool cond = (bool)fp[opData[0]];
340struct CondJmpRelativeIfTrue {
341 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
342 bool cond = (bool)fp[opData[0]];
352 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
return opData[0]; }
357 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
358 ExprVarRef* ref =
reinterpret_cast<ExprVarRef*
>(c[opData[0]]);
359 if (ref->type().isFP()) {
360 ref->eval(fp + opData[1]);
362 ref->eval(
const_cast<const char**
>(c + opData[1]));
371 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
373 double* basePointer =
reinterpret_cast<double*
>(c[0]) + opData[0];
374 double* destPointer = fp + opData[1];
375 for (
int i = 0; i < dim; i++) destPointer[i] = basePointer[i];
382template <
char uniform,
int dim>
383struct EvalVarBlockIndirect {
384 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
386 int stride = opData[2];
387 int outputVarBlockOffset = opData[0];
388 int destIndex = opData[1];
389 size_t indirectIndex =
reinterpret_cast<size_t>(c[1]);
390 double* basePointer =
391 reinterpret_cast<double**
>(c[0])[outputVarBlockOffset] + (uniform ? 0 : (stride * indirectIndex));
392 double* destPointer = fp + destIndex;
393 for (
int i = 0; i < dim; i++) destPointer[i] = basePointer[i];
403template <
char op,
int d>
405 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
407 double* in0 = fp + opData[0];
408 double* in1 = fp + opData[1];
409 double* out = fp + opData[2];
410 for (
int k = 0; k < d; k++) {
413 result &= (*in0) == (*in1);
416 result &= (*in0) != (*in1);
430struct CompareEqOp<op, 3> {
431 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
432 bool eq = fp[opData[0]] == fp[opData[1]] && fp[opData[0] + 1] == fp[opData[1] + 1] &&
433 fp[opData[0] + 2] == fp[opData[1] + 2];
434 if (op ==
'=') fp[opData[2]] = eq;
435 if (op ==
'!') fp[opData[2]] = !eq;
440template <
char op,
int d>
441struct StrCompareEqOp {
443 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
446 fp[opData[2]] = strcmp(c[opData[0]], c[opData[1]]) == 0;
449 fp[opData[2]] = strcmp(c[opData[0]], c[opData[1]]) != 0;
458int ProcedureReturn(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
459 int newPC = callStack.back();
460 callStack.pop_back();
461 return newPC - opData[0];
466int ProcedureCall(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
467 callStack.push_back(opData[0]);
476 int basePC = interpreter->
nextPC();
478 interpreter->
addOp(ProcedureReturn);
481 interpreter->
endOp(
false);
488 std::vector<int> operands;
489 for (
int c = 0; c < callerNode->
numChildren(); c++) {
494 if (callerNode->
promote(c) != 0) {
500 interpreter->
endOp();
505 interpreter->
endOp();
511 operands.push_back(operand);
517 outoperand = interpreter->
allocPtr();
521 int basePC = interpreter->
nextPC();
522 interpreter->
addOp(ProcedureCall);
523 int returnAddress = interpreter->
addOperand(0);
525 interpreter->
endOp(
false);
527 interpreter->
opData[returnAddress] = interpreter->
nextPC();
533 interpreter->
endOp();
544 int loc = interpreter->
allocFP(1);
545 interpreter->
d[loc] =
value();
551 interpreter->
s[loc] =
const_cast<char*
>(
_str.c_str());
556 std::vector<int> locs;
565 interpreter->
endOp();
571 int dim0 = child0->
type().
dim(), dim1 = child1->type().dim(), dimout =
type().
dim();
573 int op1 = child1->buildInterpreter(interpreter);
575 if (dim0 != dimout) {
577 int promoteOp0 = interpreter->
allocFP(dimout);
581 interpreter->
endOp();
583 if (dim1 != dimout) {
585 int promoteOp1 = interpreter->
allocFP(dimout);
589 interpreter->
endOp();
623 interpreter->
addOp(BinaryStringOp::f);
624 int intermediateOp = interpreter->
allocPtr();
625 interpreter->
s[intermediateOp] = (
char*)(&
_out);
637 op2 = interpreter->
allocFP(dimout);
676 int op1 = interpreter->
allocFP(dimout);
679 interpreter->
endOp();
686 int dimin = child0->
type().
dim();
688 int op1 = child1->buildInterpreter(interpreter);
689 int op2 = interpreter->
allocFP(1);
695 interpreter->
endOp();
702 Interpreter::VarToLoc::iterator i = interpreter->
varToLoc.find(
var);
703 if (i != interpreter->
varToLoc.end())
706 throw std::runtime_error(
"Unallocated variable encountered.");
711 int dim = type.dim();
712 destLoc = interpreter->
allocFP(dim);
717 if (blockVarRef->type().isLifetimeUniform())
721 interpreter->
addOperand(blockVarRef->offset());
723 interpreter->
addOperand(blockVarRef->stride());
724 interpreter->
endOp();
726 int varRefLoc = interpreter->
allocPtr();
727 interpreter->
addOp(EvalVar::f);
728 interpreter->
s[varRefLoc] =
const_cast<char*
>(
reinterpret_cast<const char*
>(
var));
731 interpreter->
endOp();
739 return interpreter->
varToLoc[
this] =
745 assert(loc != -1 &&
"Invalid type found");
749 if (child0Type.
isFP()) {
752 interpreter->
addOp(AssignStrOp::f);
754 assert(
false &&
"Invalid desired assign type");
765 int destDim = varDest->
type().
dim();
766 if (destDim != varSource->
type().
dim()) {
767 assert(varSource->
type().
dim() == 1);
774 interpreter->
endOp();
776 interpreter->
addOp(AssignStrOp::f);
779 interpreter->
endOp();
781 assert(
false &&
"failed to promote invalid type");
787 int basePC = interpreter->
nextPC();
793 for (
auto&
it : merges) {
795 if (finalVar->
valid()) {
801 interpreter->
addOp(CondJmpRelativeIfFalse::f);
804 interpreter->
endOp();
808 for (
auto&
it : merges) {
810 if (finalVar->
valid()) {
814 interpreter->
addOp(JmpRelative::f);
816 interpreter->
endOp();
819 int child2PC = interpreter->
nextPC();
821 for (
auto&
it : merges) {
823 if (finalVar->
valid()) {
829 interpreter->
opData[destFalse] = child2PC - basePC;
830 interpreter->
opData[destEnd] = interpreter->
nextPC() - (child2PC - 1);
837 assert(
type().dim() == 1 &&
type().isFP());
839 if (
_op ==
'&' ||
_op ==
'|') {
843 int op2 = interpreter->
allocFP(1);
847 int basePC = (interpreter->
nextPC());
848 interpreter->
addOp(
_op ==
'&' ? CondJmpRelativeIfFalse::f : CondJmpRelativeIfTrue::f);
851 interpreter->
endOp();
853 int op1 = child1->buildInterpreter(interpreter);
859 interpreter->
endOp();
860 interpreter->
addOp(JmpRelative::f);
862 interpreter->
endOp();
865 int falseConditionPC = interpreter->
nextPC();
866 interpreter->
addOp(AssignOp<1>::f);
869 interpreter->
endOp();
872 interpreter->
opData[destFalse] = falseConditionPC - basePC;
873 interpreter->
opData[destEnd] = interpreter->
nextPC() - (falseConditionPC - 1);
880 int op1 = child1->buildInterpreter(interpreter);
901 int op2 = interpreter->
allocFP(1);
905 interpreter->
endOp();
916 if (childType.
isFP()) {
917 int operand = interpreter->
allocFP(childType.
dim());
919 interpreter->
varToLoc[childVarNode->localVar()] = operand;
934 int op1 = child1->buildInterpreter(interpreter);
937 int dim0 = child0->
type().
dim(), dim1 = child1->type().dim();
938 int dimCompare = std::max(dim0, dim1);
939 if (dimCompare > 1) {
942 int promotedOp0 = interpreter->
allocFP(dim1);
945 interpreter->
endOp();
950 int promotedOp1 = interpreter->
allocFP(dim0);
953 interpreter->
endOp();
962 assert(
false &&
"Invalid operation");
969 assert(
false &&
"Invalid operation");
971 assert(
false &&
"Invalid type for comparison");
972 int op2 = interpreter->
allocFP(1);
987 int basePC = (interpreter->
nextPC());
988 interpreter->
addOp(CondJmpRelativeIfFalse::f);
991 interpreter->
endOp();
998 interpreter->
addOp(AssignStrOp::f);
1002 int dataOutTrue = interpreter->
addOperand(-1);
1003 interpreter->
endOp(
false);
1006 interpreter->
addOp(JmpRelative::f);
1008 interpreter->
endOp();
1011 int child2PC = interpreter->
nextPC();
1018 interpreter->
addOp(AssignStrOp::f);
1022 int dataOutFalse = interpreter->
addOperand(-1);
1023 interpreter->
endOp(
false);
1026 interpreter->
opData[destFalse] = child2PC - basePC;
1027 interpreter->
opData[destEnd] = interpreter->
nextPC() - (child2PC - 1);
1038 interpreter->
opData[dataOutTrue] = opOut;
1039 interpreter->
opData[dataOutFalse] = opOut;
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
char _op
_op '<' less-than, 'l' less-than-eq, '>' greater-than, 'g' greater-than-eq
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
Node that calls a function.
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
const ExprPrototypeNode * prototype() const
TODO: Accessor for prototype (probably not needed when we use prep right)
int buildInterpreter(Interpreter *interpreter) const
Build the interpreter.
int buildInterpreterForCall(const ExprFuncNode *callerNode, Interpreter *interpreter) const
Build interpreter if we are called.
ExprLocalVar join (merge) references. Remembers which variables are possible assigners to this.
ExprLocalVar reference, all local variables in seexpr are subclasses of this or this itself.
ExprType type() const
returns type of the variable
int buildInterpreter(Interpreter *interpreter) const
Allocates variable for interpreter.
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
int numChildren() const
Number of children.
const ExprNode * child(size_t i) const
Get 0 indexed child.
const ExprType & type() const
The type of the node.
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const
Build the interpreter.
std::vector< int > _interpreterOps
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
bool isFP() const
Direct is predicate checks.
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
std::vector< std::pair< std::string, ExprLocalVarPhi * > > & merge(size_t index)
Node that references a variable.
const ExprVarRef * var() const
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
abstract class for implementing variable references
virtual ExprType type() const
returns (current) type
virtual int buildInterpreter(Interpreter *interpreter) const
builds an interpreter. Returns the location index for the evaluated data
void setPCStart(int pcStart)
int allocFP(int n)
! Allocate a floating point set of data of dimension n
int addOp(OpF op)
! adds an operator to the program (pointing to the data at the current location)
std::vector< std::pair< OpF, int > > ops
int(*) OpF(int *, double *, char **, std::vector< int > &)
Op function pointer arguments are (int* currOpData,double* currD,char** c,std::stack<int>& callStacku...
void eval(VarBlock *varBlock, bool debug=false)
Evaluate program.
int addOperand(int param)
! Adds an operand. Note this should be done after doing the addOp!
int allocPtr()
Allocate a pointer location (can be anything, but typically space for char*)
int nextPC()
Return the position that the next instruction will be placed at.
void endOp(bool execute=true)
std::vector< int > opData
Ooperands to op.
std::vector< double > d
Double data (constants and evaluated)
std::vector< char * > s
constant and evaluated pointer data
void print(int pc=-1) const
Debug by printing program.
std::vector< int > callStack
Internally implemented var ref used by SeExpr.
A thread local evaluation context. Just allocate and fill in with data.
std::vector< double > d
copy of Interpreter's double data
int indirectIndex
indirect index to add to pointer based data
char ** data()
Raw data of the data block pointer (used by compiler)
bool threadSafe
if true, interpreter's data will be copied to this instance before evaluation.
std::vector< char * > s
copy of Interpreter's str data
you may not use this file except in compliance with the License and the following modification to it
T_FUNCTYPE getTemplatizedOp(int i)
Return the function f encapsulated in class T for the dynamic i converted to a static d.
const ExprStrNode * isString(const ExprNode *testee)
void copyVarToPromotedPosition(Interpreter *interpreter, ExprLocalVar *varSource, ExprLocalVar *varDest)
static Interpreter::OpF getTemplatizedOp2(int i)
Return the function f encapsulated in class T for the dynamic i converted to a static d....
< br > pow($a, 0.5)+ $b< br >< br ></div > External variables can also be overridden by local assignment.  
with numParticles numAttributes A variable block contains variable names and types but doesn t care what the values are< pre > void f(const std::string &s, MyParticleData *p, int outputDim=3)