Simplify layout of Expr.
Make the union anonymous so that its elements can be addressed directly. Then, move the Expr *b field into the union, as it already is never used at the same time as any of the union members.pull/4/head
parent
158c66b1b4
commit
84a6511cfc
88
src/expr.cpp
88
src/expr.cpp
|
@ -214,7 +214,7 @@ Expr *ExprQuaternion::Magnitude(void) {
|
||||||
Expr *Expr::From(hParam p) {
|
Expr *Expr::From(hParam p) {
|
||||||
Expr *r = AllocExpr();
|
Expr *r = AllocExpr();
|
||||||
r->op = PARAM;
|
r->op = PARAM;
|
||||||
r->x.parh = p;
|
r->parh = p;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ Expr *Expr::From(double v) {
|
||||||
|
|
||||||
Expr *r = AllocExpr();
|
Expr *r = AllocExpr();
|
||||||
r->op = CONSTANT;
|
r->op = CONSTANT;
|
||||||
r->x.v = v;
|
r->v = v;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,14 +315,14 @@ Expr *Expr::DeepCopyWithParamsAsPointers(IdList<Param,hParam> *firstTry,
|
||||||
// A param that is referenced by its hParam gets rewritten to go
|
// A param that is referenced by its hParam gets rewritten to go
|
||||||
// straight in to the parameter table with a pointer, or simply
|
// straight in to the parameter table with a pointer, or simply
|
||||||
// into a constant if it's already known.
|
// into a constant if it's already known.
|
||||||
Param *p = firstTry->FindByIdNoOops(x.parh);
|
Param *p = firstTry->FindByIdNoOops(parh);
|
||||||
if(!p) p = thenTry->FindById(x.parh);
|
if(!p) p = thenTry->FindById(parh);
|
||||||
if(p->known) {
|
if(p->known) {
|
||||||
n->op = CONSTANT;
|
n->op = CONSTANT;
|
||||||
n->x.v = p->val;
|
n->v = p->val;
|
||||||
} else {
|
} else {
|
||||||
n->op = PARAM_PTR;
|
n->op = PARAM_PTR;
|
||||||
n->x.parp = p;
|
n->parp = p;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -336,10 +336,10 @@ Expr *Expr::DeepCopyWithParamsAsPointers(IdList<Param,hParam> *firstTry,
|
||||||
|
|
||||||
double Expr::Eval(void) {
|
double Expr::Eval(void) {
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case PARAM: return SK.GetParam(x.parh)->val;
|
case PARAM: return SK.GetParam(parh)->val;
|
||||||
case PARAM_PTR: return (x.parp)->val;
|
case PARAM_PTR: return parp->val;
|
||||||
|
|
||||||
case CONSTANT: return x.v;
|
case CONSTANT: return v;
|
||||||
|
|
||||||
case PLUS: return a->Eval() + b->Eval();
|
case PLUS: return a->Eval() + b->Eval();
|
||||||
case MINUS: return a->Eval() - b->Eval();
|
case MINUS: return a->Eval() - b->Eval();
|
||||||
|
@ -362,8 +362,8 @@ Expr *Expr::PartialWrt(hParam p) {
|
||||||
Expr *da, *db;
|
Expr *da, *db;
|
||||||
|
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case PARAM_PTR: return From(p.v == x.parp->h.v ? 1 : 0);
|
case PARAM_PTR: return From(p.v == parp->h.v ? 1 : 0);
|
||||||
case PARAM: return From(p.v == x.parh.v ? 1 : 0);
|
case PARAM: return From(p.v == parh.v ? 1 : 0);
|
||||||
|
|
||||||
case CONSTANT: return From(0.0);
|
case CONSTANT: return From(0.0);
|
||||||
|
|
||||||
|
@ -403,8 +403,8 @@ Expr *Expr::PartialWrt(hParam p) {
|
||||||
|
|
||||||
uint64_t Expr::ParamsUsed(void) {
|
uint64_t Expr::ParamsUsed(void) {
|
||||||
uint64_t r = 0;
|
uint64_t r = 0;
|
||||||
if(op == PARAM) r |= ((uint64_t)1 << (x.parh.v % 61));
|
if(op == PARAM) r |= ((uint64_t)1 << (parh.v % 61));
|
||||||
if(op == PARAM_PTR) r |= ((uint64_t)1 << (x.parp->h.v % 61));
|
if(op == PARAM_PTR) r |= ((uint64_t)1 << (parp->h.v % 61));
|
||||||
|
|
||||||
int c = Children();
|
int c = Children();
|
||||||
if(c >= 1) r |= a->ParamsUsed();
|
if(c >= 1) r |= a->ParamsUsed();
|
||||||
|
@ -413,8 +413,8 @@ uint64_t Expr::ParamsUsed(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Expr::DependsOn(hParam p) {
|
bool Expr::DependsOn(hParam p) {
|
||||||
if(op == PARAM) return (x.parh.v == p.v);
|
if(op == PARAM) return (parh.v == p.v);
|
||||||
if(op == PARAM_PTR) return (x.parp->h.v == p.v);
|
if(op == PARAM_PTR) return (parp->h.v == p.v);
|
||||||
|
|
||||||
int c = Children();
|
int c = Children();
|
||||||
if(c == 1) return a->DependsOn(p);
|
if(c == 1) return a->DependsOn(p);
|
||||||
|
@ -447,29 +447,29 @@ Expr *Expr::FoldConstants(void) {
|
||||||
if(n->a->op == CONSTANT && n->b->op == CONSTANT) {
|
if(n->a->op == CONSTANT && n->b->op == CONSTANT) {
|
||||||
double nv = n->Eval();
|
double nv = n->Eval();
|
||||||
n->op = CONSTANT;
|
n->op = CONSTANT;
|
||||||
n->x.v = nv;
|
n->v = nv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// x + 0 = 0 + x = x
|
// x + 0 = 0 + x = x
|
||||||
if(op == PLUS && n->b->op == CONSTANT && Tol(n->b->x.v, 0)) {
|
if(op == PLUS && n->b->op == CONSTANT && Tol(n->b->v, 0)) {
|
||||||
*n = *(n->a); break;
|
*n = *(n->a); break;
|
||||||
}
|
}
|
||||||
if(op == PLUS && n->a->op == CONSTANT && Tol(n->a->x.v, 0)) {
|
if(op == PLUS && n->a->op == CONSTANT && Tol(n->a->v, 0)) {
|
||||||
*n = *(n->b); break;
|
*n = *(n->b); break;
|
||||||
}
|
}
|
||||||
// 1*x = x*1 = x
|
// 1*x = x*1 = x
|
||||||
if(op == TIMES && n->b->op == CONSTANT && Tol(n->b->x.v, 1)) {
|
if(op == TIMES && n->b->op == CONSTANT && Tol(n->b->v, 1)) {
|
||||||
*n = *(n->a); break;
|
*n = *(n->a); break;
|
||||||
}
|
}
|
||||||
if(op == TIMES && n->a->op == CONSTANT && Tol(n->a->x.v, 1)) {
|
if(op == TIMES && n->a->op == CONSTANT && Tol(n->a->v, 1)) {
|
||||||
*n = *(n->b); break;
|
*n = *(n->b); break;
|
||||||
}
|
}
|
||||||
// 0*x = x*0 = 0
|
// 0*x = x*0 = 0
|
||||||
if(op == TIMES && n->b->op == CONSTANT && Tol(n->b->x.v, 0)) {
|
if(op == TIMES && n->b->op == CONSTANT && Tol(n->b->v, 0)) {
|
||||||
n->op = CONSTANT; n->x.v = 0; break;
|
n->op = CONSTANT; n->v = 0; break;
|
||||||
}
|
}
|
||||||
if(op == TIMES && n->a->op == CONSTANT && Tol(n->a->x.v, 0)) {
|
if(op == TIMES && n->a->op == CONSTANT && Tol(n->a->v, 0)) {
|
||||||
n->op = CONSTANT; n->x.v = 0; break;
|
n->op = CONSTANT; n->v = 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -484,7 +484,7 @@ Expr *Expr::FoldConstants(void) {
|
||||||
if(n->a->op == CONSTANT) {
|
if(n->a->op == CONSTANT) {
|
||||||
double nv = n->Eval();
|
double nv = n->Eval();
|
||||||
n->op = CONSTANT;
|
n->op = CONSTANT;
|
||||||
n->x.v = nv;
|
n->v = nv;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -496,8 +496,8 @@ Expr *Expr::FoldConstants(void) {
|
||||||
void Expr::Substitute(hParam oldh, hParam newh) {
|
void Expr::Substitute(hParam oldh, hParam newh) {
|
||||||
if(op == PARAM_PTR) oops();
|
if(op == PARAM_PTR) oops();
|
||||||
|
|
||||||
if(op == PARAM && x.parh.v == oldh.v) {
|
if(op == PARAM && parh.v == oldh.v) {
|
||||||
x.parh = newh;
|
parh = newh;
|
||||||
}
|
}
|
||||||
int c = Children();
|
int c = Children();
|
||||||
if(c >= 1) a->Substitute(oldh, newh);
|
if(c >= 1) a->Substitute(oldh, newh);
|
||||||
|
@ -513,8 +513,8 @@ const hParam Expr::NO_PARAMS = { 0 };
|
||||||
const hParam Expr::MULTIPLE_PARAMS = { 1 };
|
const hParam Expr::MULTIPLE_PARAMS = { 1 };
|
||||||
hParam Expr::ReferencedParams(ParamList *pl) {
|
hParam Expr::ReferencedParams(ParamList *pl) {
|
||||||
if(op == PARAM) {
|
if(op == PARAM) {
|
||||||
if(pl->FindByIdNoOops(x.parh)) {
|
if(pl->FindByIdNoOops(parh)) {
|
||||||
return x.parh;
|
return parh;
|
||||||
} else {
|
} else {
|
||||||
return NO_PARAMS;
|
return NO_PARAMS;
|
||||||
}
|
}
|
||||||
|
@ -552,10 +552,10 @@ std::string Expr::Print(void) {
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
switch(op) {
|
switch(op) {
|
||||||
case PARAM: return ssprintf("param(%08x)", x.parh.v);
|
case PARAM: return ssprintf("param(%08x)", parh.v);
|
||||||
case PARAM_PTR: return ssprintf("param(p%08x)", x.parp->h.v);
|
case PARAM_PTR: return ssprintf("param(p%08x)", parp->h.v);
|
||||||
|
|
||||||
case CONSTANT: return ssprintf("%.3f", x.v);
|
case CONSTANT: return ssprintf("%.3f", v);
|
||||||
|
|
||||||
case PLUS: c = '+'; goto p;
|
case PLUS: c = '+'; goto p;
|
||||||
case MINUS: c = '-'; goto p;
|
case MINUS: c = '-'; goto p;
|
||||||
|
@ -628,7 +628,7 @@ int Expr::Precedence(Expr *e) {
|
||||||
if(e->op == ALL_RESOLVED) return -1; // never want to reduce this marker
|
if(e->op == ALL_RESOLVED) return -1; // never want to reduce this marker
|
||||||
if(e->op != BINARY_OP && e->op != UNARY_OP) oops();
|
if(e->op != BINARY_OP && e->op != UNARY_OP) oops();
|
||||||
|
|
||||||
switch(e->x.c) {
|
switch(e->c) {
|
||||||
case 'q':
|
case 'q':
|
||||||
case 's':
|
case 's':
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -650,7 +650,7 @@ void Expr::Reduce(void) {
|
||||||
Expr *op = PopOperator();
|
Expr *op = PopOperator();
|
||||||
Expr *n;
|
Expr *n;
|
||||||
int o;
|
int o;
|
||||||
switch(op->x.c) {
|
switch(op->c) {
|
||||||
case '+': o = PLUS; goto c;
|
case '+': o = PLUS; goto c;
|
||||||
case '-': o = MINUS; goto c;
|
case '-': o = MINUS; goto c;
|
||||||
case '*': o = TIMES; goto c;
|
case '*': o = TIMES; goto c;
|
||||||
|
@ -690,21 +690,21 @@ void Expr::Parse(void) {
|
||||||
if(n->op == CONSTANT) {
|
if(n->op == CONSTANT) {
|
||||||
PushOperand(n);
|
PushOperand(n);
|
||||||
Consume();
|
Consume();
|
||||||
} else if(n->op == PAREN && n->x.c == '(') {
|
} else if(n->op == PAREN && n->c == '(') {
|
||||||
Consume();
|
Consume();
|
||||||
Parse();
|
Parse();
|
||||||
n = Next();
|
n = Next();
|
||||||
if(n->op != PAREN || n->x.c != ')') throw "expected: )";
|
if(n->op != PAREN || n->c != ')') throw "expected: )";
|
||||||
Consume();
|
Consume();
|
||||||
} else if(n->op == UNARY_OP) {
|
} else if(n->op == UNARY_OP) {
|
||||||
PushOperator(n);
|
PushOperator(n);
|
||||||
Consume();
|
Consume();
|
||||||
continue;
|
continue;
|
||||||
} else if(n->op == BINARY_OP && n->x.c == '-') {
|
} else if(n->op == BINARY_OP && n->c == '-') {
|
||||||
// The minus sign is special, because it might be binary or
|
// The minus sign is special, because it might be binary or
|
||||||
// unary, depending on context.
|
// unary, depending on context.
|
||||||
n->op = UNARY_OP;
|
n->op = UNARY_OP;
|
||||||
n->x.c = 'n';
|
n->c = 'n';
|
||||||
PushOperator(n);
|
PushOperator(n);
|
||||||
Consume();
|
Consume();
|
||||||
continue;
|
continue;
|
||||||
|
@ -743,7 +743,7 @@ void Expr::Lex(const char *in) {
|
||||||
number[len++] = '\0';
|
number[len++] = '\0';
|
||||||
Expr *e = AllocExpr();
|
Expr *e = AllocExpr();
|
||||||
e->op = CONSTANT;
|
e->op = CONSTANT;
|
||||||
e->x.v = atof(number);
|
e->v = atof(number);
|
||||||
Unparsed[UnparsedCnt++] = e;
|
Unparsed[UnparsedCnt++] = e;
|
||||||
} else if(isalpha(c) || c == '_') {
|
} else if(isalpha(c) || c == '_') {
|
||||||
char name[70];
|
char name[70];
|
||||||
|
@ -757,16 +757,16 @@ void Expr::Lex(const char *in) {
|
||||||
Expr *e = AllocExpr();
|
Expr *e = AllocExpr();
|
||||||
if(strcmp(name, "sqrt")==0) {
|
if(strcmp(name, "sqrt")==0) {
|
||||||
e->op = UNARY_OP;
|
e->op = UNARY_OP;
|
||||||
e->x.c = 'q';
|
e->c = 'q';
|
||||||
} else if(strcmp(name, "cos")==0) {
|
} else if(strcmp(name, "cos")==0) {
|
||||||
e->op = UNARY_OP;
|
e->op = UNARY_OP;
|
||||||
e->x.c = 'c';
|
e->c = 'c';
|
||||||
} else if(strcmp(name, "sin")==0) {
|
} else if(strcmp(name, "sin")==0) {
|
||||||
e->op = UNARY_OP;
|
e->op = UNARY_OP;
|
||||||
e->x.c = 's';
|
e->c = 's';
|
||||||
} else if(strcmp(name, "pi")==0) {
|
} else if(strcmp(name, "pi")==0) {
|
||||||
e->op = CONSTANT;
|
e->op = CONSTANT;
|
||||||
e->x.v = PI;
|
e->v = PI;
|
||||||
} else {
|
} else {
|
||||||
throw "unknown name";
|
throw "unknown name";
|
||||||
}
|
}
|
||||||
|
@ -774,7 +774,7 @@ void Expr::Lex(const char *in) {
|
||||||
} else if(strchr("+-*/()", c)) {
|
} else if(strchr("+-*/()", c)) {
|
||||||
Expr *e = AllocExpr();
|
Expr *e = AllocExpr();
|
||||||
e->op = (c == '(' || c == ')') ? PAREN : BINARY_OP;
|
e->op = (c == '(' || c == ')') ? PAREN : BINARY_OP;
|
||||||
e->x.c = c;
|
e->c = c;
|
||||||
Unparsed[UnparsedCnt++] = e;
|
Unparsed[UnparsedCnt++] = e;
|
||||||
in++;
|
in++;
|
||||||
} else if(isspace(c)) {
|
} else if(isspace(c)) {
|
||||||
|
|
|
@ -52,19 +52,19 @@ public:
|
||||||
|
|
||||||
int op;
|
int op;
|
||||||
Expr *a;
|
Expr *a;
|
||||||
Expr *b;
|
|
||||||
union {
|
union {
|
||||||
double v;
|
double v;
|
||||||
hParam parh;
|
hParam parh;
|
||||||
Param *parp;
|
Param *parp;
|
||||||
hEntity entity;
|
hEntity entity;
|
||||||
|
Expr *b;
|
||||||
|
|
||||||
// For use while parsing
|
// For use while parsing
|
||||||
char c;
|
char c;
|
||||||
} x;
|
};
|
||||||
|
|
||||||
Expr() { }
|
Expr() { }
|
||||||
Expr(double v) : op(CONSTANT) { x.v = v; }
|
Expr(double val) : op(CONSTANT) { v = val; }
|
||||||
|
|
||||||
static inline Expr *AllocExpr(void)
|
static inline Expr *AllocExpr(void)
|
||||||
{ return (Expr *)AllocTemporary(sizeof(Expr)); }
|
{ return (Expr *)AllocTemporary(sizeof(Expr)); }
|
||||||
|
|
|
@ -94,8 +94,8 @@ void System::SolveBySubstitution(void) {
|
||||||
tex->a->op == Expr::PARAM &&
|
tex->a->op == Expr::PARAM &&
|
||||||
tex->b->op == Expr::PARAM)
|
tex->b->op == Expr::PARAM)
|
||||||
{
|
{
|
||||||
hParam a = (tex->a)->x.parh;
|
hParam a = tex->a->parh;
|
||||||
hParam b = (tex->b)->x.parh;
|
hParam b = tex->b->parh;
|
||||||
if(!(param.FindByIdNoOops(a) && param.FindByIdNoOops(b))) {
|
if(!(param.FindByIdNoOops(a) && param.FindByIdNoOops(b))) {
|
||||||
// Don't substitute unless they're both solver params;
|
// Don't substitute unless they're both solver params;
|
||||||
// otherwise it's an equation that can be solved immediately,
|
// otherwise it's an equation that can be solved immediately,
|
||||||
|
|
Loading…
Reference in New Issue