22 double* fp =
d.data();
23 char** str =
s.data();
28 if (
block->threadSafe ==
true) {
32 memcpy(fp,
d.data(),
d.size() *
sizeof(
double));
36 str =
block->s.data();
37 memcpy(str,
s.data(),
s.size() *
sizeof(
char*));
41 str[0] =
reinterpret_cast<char*
>(
block->data());
42 str[1] =
reinterpret_cast<char*
>(
static_cast<size_t>(
block->indirectIndex));
46 int end =
static_cast<int>(
ops.size());
49 std::cerr <<
"Running op at " <<
pc << std::endl;
52 const std::pair<OpF, int>&
op =
ops[
pc];
60 std::cerr <<
"---- ops ----------------------" << std::endl;
61 for (
size_t i = 0;
i <
ops.size();
i++) {
62 const char *name =
"";
66 name =
info.dli_sname;
75 std::cerr <<
"---- opdata ----------------------" << std::endl;
76 for (
size_t k = 0;
k <
opData.size();
k++) {
77 std::cerr <<
"opData[" <<
k <<
"]= " <<
opData[
k] << std::endl;
79 std::cerr <<
"----- fp --------------------------" << std::endl;
80 for (
size_t k = 0;
k <
d.size();
k++) {
81 std::cerr <<
"fp[" <<
k <<
"]= " <<
d[
k] << std::endl;
83 std::cerr <<
"---- str ----------------------" << std::endl;
84 std::cerr <<
"s[0] reserved for datablock = " <<
reinterpret_cast<size_t>(
s[0]) << std::endl;
85 std::cerr <<
"s[1] is indirectIndex = " <<
reinterpret_cast<size_t>(
s[1]) << std::endl;
86 for (
size_t k = 2;
k <
s.size();
k++) {
87 std::cerr <<
"s[" <<
k <<
"]= " << (
void *)(
s[
k]);
91 std::cerr << std::endl;
102template <
char c,
template <
char c1,
int d>
class T>
138 assert(
false &&
"Invalid dynamic parameter (not supported template)");
147struct BinaryStringOp {
148 static int f(
int* opData,
double*,
char** c, std::vector<int>&) {
150 char*& out = *(
char**)c[opData[0]];
151 char* in1 = c[opData[1]];
152 char* in2 = c[opData[2]];
157 size_t len1 = strlen(in1);
158 size_t len2 = strlen(in2);
159 if (out ==
nullptr || len1 + len2 + 1 > strlen(out))
162 out =
new char [len1 + len2 + 1];
166 memset(out, 0, len1 + len2 + 1);
170 strcat(out + len1, in2);
171 out[len1 + len2] =
'\0';
181template <
char op,
int d>
183 static double niceMod(
double a,
double b) {
184 if (b == 0)
return 0;
185 return a -
floor(a / b) * b;
188 static int f(
int* opData,
double* fp,
char**, std::vector<int>& ) {
189 double* in1 = fp + opData[0];
190 double* in2 = fp + opData[1];
191 double* out = fp + opData[2];
193 for (
int k = 0; k < d; k++) {
196 *out = (*in1) + (*in2);
199 *out = (*in1) - (*in2);
202 *out = (*in1) * (*in2);
205 *out = (*in1) / (*in2);
208 *out = niceMod(*in1, *in2);
211 *out = pow(*in1, *in2);
215 *out = (*in1) < (*in2);
218 *out = (*in1) > (*in2);
221 *out = (*in1) <= (*in2);
224 *out = (*in1) >= (*in2);
227 *out = (*in1) && (*in2);
230 *out = (*in1) || (*in2);
244template <
char op,
int d>
246 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
247 double* in = fp + opData[0];
248 double* out = fp + opData[1];
249 for (
int k = 0; k < d; k++) {
273 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
274 int tuple = opData[0];
275 int subscript = int(fp[opData[1]]);
277 if (subscript >= d || subscript < 0)
280 fp[out] = fp[tuple + subscript];
288 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
290 for (
int k = 0; k < d; k++) {
291 fp[out + k] = fp[opData[k]];
300 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
303 for (
int k = 0; k < d; k++) {
304 fp[out + k] = fp[in + k];
312 static int f(
int* opData,
double*,
char** c, std::vector<int>&) {
321struct CondJmpRelativeIfFalse {
322 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
323 bool cond = (bool)fp[opData[0]];
332struct CondJmpRelativeIfTrue {
333 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
334 bool cond = (bool)fp[opData[0]];
344 static int f(
int* opData,
double*,
char**, std::vector<int>&) {
return opData[0]; }
349 static int f(
int* opData,
double* fp,
char** c, std::vector<int>&) {
350 auto* ref =
reinterpret_cast<ExprVarRef*
>(c[opData[0]]);
351 if (ref->type().isFP()) {
352 ref->eval(fp + opData[1]);
354 ref->eval(
const_cast<const char**
>(c + opData[1]));
363 static int f(
int* opData,
double* fp,
char** c, std::vector<int>& callStack) {
365 double* basePointer =
reinterpret_cast<double*
>(c[0]) + opData[0];
366 double* destPointer = fp + opData[1];
367 for (
int i = 0; i < dim; i++) destPointer[i] = basePointer[i];
374template <
char uniform,
int dim>
375struct EvalVarBlockIndirect {
376 static int f(
int* opData,
double* fp,
char** c, std::vector<int>&) {
378 int stride = opData[2];
379 int outputVarBlockOffset = opData[0];
380 int destIndex = opData[1];
381 auto indirectIndex =
reinterpret_cast<size_t>(c[1]);
382 double* basePointer =
383 reinterpret_cast<double**
>(c[0])[outputVarBlockOffset] + (uniform ? 0 : (stride * indirectIndex));
384 double* destPointer = fp + destIndex;
385 for (
int i = 0; i < dim; i++) destPointer[i] = basePointer[i];
395template <
char op,
int d>
397 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
399 double* in0 = fp + opData[0];
400 double* in1 = fp + opData[1];
401 double* out = fp + opData[2];
402 for (
int k = 0; k < d; k++) {
405 result &= (*in0) == (*in1);
408 result &= (*in0) != (*in1);
422struct CompareEqOp<op, 3> {
423 static int f(
int* opData,
double* fp,
char**, std::vector<int>&) {
424 bool eq = fp[opData[0]] == fp[opData[1]] && fp[opData[0] + 1] == fp[opData[1] + 1] &&
425 fp[opData[0] + 2] == fp[opData[1] + 2];
426 if (op ==
'=') fp[opData[2]] = eq;
427 if (op ==
'!') fp[opData[2]] = !eq;
432template <
char op,
int d>
433struct StrCompareEqOp {
435 static int f(
int* opData,
double* fp,
char** c, std::vector<int>&) {
438 fp[opData[2]] = strcmp(c[opData[0]], c[opData[1]]) == 0;
441 fp[opData[2]] = strcmp(c[opData[0]], c[opData[1]]) != 0;
450int ProcedureReturn(
int* opData,
double*,
char**, std::vector<int>& callStack) {
451 int newPC = callStack.back();
452 callStack.pop_back();
453 return newPC - opData[0];
458int ProcedureCall(
int* opData,
double*,
char**, std::vector<int>& callStack) {
459 callStack.push_back(opData[0]);
481 for (
int c = 0; c <
callerNode->numChildren(); c++) {
485 if (
child->type().isFP()) {
548 std::vector<int>
locs;
702 throw std::runtime_error(
"Unallocated variable encountered.");
707 int dim =
type.dim();
741 assert(
loc != -1 &&
"Invalid type found");
750 assert(
false &&
"Invalid desired assign type");
771 }
else if (
varDest->type().isString()) {
777 assert(
false &&
"failed to promote invalid type");
836 if (
_op ==
'&' ||
_op ==
'|') {
845 interpreter->addOp(
_op ==
'&' ? CondJmpRelativeIfFalse::f : CondJmpRelativeIfTrue::f);
934 if (
child0->type().isFP()) {
961 assert(
false &&
"Invalid operation");
962 }
else if (
child0->type().isString()) {
968 assert(
false &&
"Invalid operation");
970 assert(
false &&
"Invalid type for comparison");
1031 else if (
type().isString())
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
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
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
Node that calls a function.
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
Build the interpreter.
int buildInterpreterForCall(const ExprFuncNode *callerNode, Interpreter *interpreter) const
Build interpreter if we are called.
const ExprPrototypeNode * prototype() const
TODO: Accessor for prototype (probably not needed when we use prep right)
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.
int buildInterpreter(Interpreter *interpreter) const
Allocates variable for interpreter.
int buildInterpreter(Interpreter *interpreter) const override
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
const ExprType & type() const
The type of the node.
int numChildren() const
Number of children.
const ExprNode * child(size_t i) const
Get 0 indexed child.
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
Build the interpreter.
std::vector< int > _interpreterOps
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
bool isFP() const
Direct is predicate checks.
int buildInterpreter(Interpreter *interpreter) const override
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.
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
const ExprVarRef * var() const
abstract class for implementing variable references
int buildInterpreter(Interpreter *interpreter) const override
builds an interpreter. Returns the location index for the evaluated data
std::vector< std::pair< OpF, int > > ops
std::vector< double > d
Double data (constants and evaluated)
void eval(VarBlock *varBlock, bool debug=false)
Evaluate program.
std::vector< int > callStack
std::vector< char * > s
constant and evaluated pointer data
int(*)(int *, double *, char **, std::vector< int > &) OpF
Op function pointer arguments are (int* currOpData,double* currD,char** c,std::stack<int>& callStacku...
std::vector< int > opData
Ooperands to op.
void print(int pc=-1) const
Debug by printing program.
Internally implemented var ref used by SeExpr.
A thread local evaluation context. Just allocate and fill in with data.
KSeExpr_DEFAULT double_t floor(double_t val)
static Interpreter::OpF getTemplatizedOp2(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)