virtual Expr::eval()

This commit is contained in:
Matthew Bellew
2018-05-08 21:56:22 -07:00
parent 2a3a5315f5
commit 39b74ef528
4 changed files with 98 additions and 94 deletions

View File

@ -84,7 +84,7 @@ public:
static int init_infix_ops();
static int destroy_infix_ops();
void reset_engine_vars();
GenExpr * clone_gen_expr(GenExpr * gen_expr);
TreeExpr * clone_tree_expr(TreeExpr * tree_expr);
ValExpr * clone_val_expr(ValExpr * val_expr);

View File

@ -27,34 +27,25 @@
#include <iostream>
#include "Eval.hpp"
float GenExpr::eval_gen_expr ( int mesh_i, int mesh_j )
float GenExpr::eval ( int mesh_i, int mesh_j )
{
float l;
if (item == 0)
return EVAL_ERROR;
switch ( this->type )
{ /* N.B. this code is responsible for 75% of all CPU time. making it faster will help a lot. */
case VAL_T:
return ( ( ValExpr* ) item )->eval_val_expr ( mesh_i, mesh_j );
case PREFUN_T:
l = ( ( PrefunExpr * ) item )->eval_prefun_expr ( mesh_i, mesh_j );
//if (EVAL_DEBUG) DWRITE( "eval_gen_expr: prefix function return value: %f\n", l);
return l;
case TREE_T:
return ( ( TreeExpr* ) ( item ) )->eval_tree_expr ( mesh_i, mesh_j );
return item->eval( mesh_i, mesh_j );
default:
return EVAL_ERROR;
}
}
/* Evaluates functions in prefix form */
float PrefunExpr::eval_prefun_expr ( int mesh_i, int mesh_j )
float PrefunExpr::eval ( int mesh_i, int mesh_j )
{
assert ( func_ptr );
float arg_list_stk[10];
@ -92,19 +83,23 @@ float PrefunExpr::eval_prefun_expr ( int mesh_i, int mesh_j )
}
/* Evaluates a value expression */
float ValExpr::eval_val_expr ( int mesh_i, int mesh_j )
// private subclasses of ValExpr -- ConstantExpr, ParameterExpr
class ConstantExpr : public ValExpr
{
public:
ConstantExpr( int type, Term *term ) : ValExpr(type,term) {}
float eval(int mesh_i, int mesh_j ) { return term.constant; }
};
class ParameterExpr : public ValExpr
{
public:
ParameterExpr( int type, Term *term ) : ValExpr(type,term) {}
float eval(int mesh_i, int mesh_j );
};
/* Value is a constant, return the float value */
if ( type == CONSTANT_TERM_T )
{
return ( term.constant );
}
/* Value is variable, dereference it */
if ( type == PARAM_TERM_T )
/* Evaluates a value expression */
float ParameterExpr::eval ( int mesh_i, int mesh_j )
{
switch ( term.param->type )
{
@ -146,48 +141,44 @@ float ValExpr::eval_val_expr ( int mesh_i, int mesh_j )
return EVAL_ERROR;
}
}
/* Unknown type, return failure */
return PROJECTM_FAILURE;
/* This could be optimized a lot more if we could return an Expr instead of a TreeExpr */
TreeExpr * TreeExpr::create( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, TreeExpr * _right )
{
float defautFloat = _infix_op == Eval::infix_mult ? 1.0f : 0.0f;
if (_infix_op == NULL)
{
if (_gen_expr == NULL)
_gen_expr = GenExpr::const_to_expr(0.0f);
}
else
{
if (_left == NULL)
_left = new TreeExpr(NULL, GenExpr::const_to_expr(defautFloat), NULL, NULL);
if (_right == NULL)
_right = new TreeExpr(NULL, GenExpr::const_to_expr(defautFloat), NULL, NULL);
}
return new TreeExpr( _infix_op, _gen_expr, _left, _right);
}
/* Evaluates an expression tree */
float TreeExpr::eval_tree_expr ( int mesh_i, int mesh_j )
float TreeExpr::eval ( int mesh_i, int mesh_j )
{
float left_arg, right_arg;
/* A leaf node, evaluate the general expression. If the expression is null as well, return zero */
if ( infix_op == NULL )
{
if ( gen_expr == NULL )
return 0;
else
return gen_expr->eval_gen_expr ( mesh_i, mesh_j );
return gen_expr->eval( mesh_i, mesh_j );
}
/* Otherwise, this node is an infix operator. Evaluate
accordingly */
/* Safe guard in case the user gave a partially written expression */
if (left == NULL) {
if (infix_op == Eval::infix_mult)
left_arg = 1;
else
left_arg = 0;
}
else
left_arg = left->eval_tree_expr ( mesh_i, mesh_j );
/* Safe guard in case the user gave a partially written expression */
if (right == NULL) {
if (infix_op == Eval::infix_mult)
right_arg = 1;
else
right_arg = 0;
}
else
right_arg = right->eval_tree_expr ( mesh_i, mesh_j );
left_arg = left->eval ( mesh_i, mesh_j );
right_arg = right->eval ( mesh_i, mesh_j );
switch ( infix_op->type )
{
@ -230,10 +221,10 @@ GenExpr * GenExpr::const_to_expr ( float val )
term.constant = val;
if ( ( val_expr = new ValExpr ( CONSTANT_TERM_T, &term ) ) == NULL )
if ( ( val_expr = ValExpr::create( CONSTANT_TERM_T, &term ) ) == NULL )
return NULL;
gen_expr = new GenExpr ( VAL_T, ( void* ) val_expr );
gen_expr = new GenExpr ( VAL_T, val_expr );
if ( gen_expr == NULL )
{
@ -269,10 +260,10 @@ GenExpr * GenExpr::param_to_expr ( Param * param )
term.param = param;
if ( ( val_expr = new ValExpr ( PARAM_TERM_T, &term ) ) == NULL )
if ( ( val_expr = ValExpr::create( PARAM_TERM_T, &term ) ) == NULL )
return NULL;
if ( ( gen_expr = new GenExpr ( VAL_T, ( void* ) val_expr ) ) == NULL )
if ( ( gen_expr = new GenExpr ( VAL_T, val_expr ) ) == NULL )
{
delete val_expr;
return NULL;
@ -296,7 +287,7 @@ GenExpr * GenExpr::prefun_to_expr ( float ( *func_ptr ) ( void * ), GenExpr ** e
prefun_expr->func_ptr = ( float ( * ) ( void* ) ) func_ptr;
prefun_expr->expr_list = expr_list;
gen_expr = new GenExpr ( PREFUN_T, ( void* ) prefun_expr );
gen_expr = new GenExpr ( PREFUN_T, prefun_expr );
if ( gen_expr == NULL )
delete prefun_expr;
@ -305,7 +296,7 @@ GenExpr * GenExpr::prefun_to_expr ( float ( *func_ptr ) ( void * ), GenExpr ** e
}
/* Creates a new tree expression */
TreeExpr::TreeExpr ( InfixOp * _infix_op, GenExpr * _gen_expr, TreeExpr * _left, TreeExpr * _right ) :
TreeExpr::TreeExpr ( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, TreeExpr * _right ) :
infix_op ( _infix_op ), gen_expr ( _gen_expr ),
left ( _left ), right ( _right ) {}
@ -313,33 +304,31 @@ TreeExpr::TreeExpr ( InfixOp * _infix_op, GenExpr * _gen_expr, TreeExpr * _left,
/* Creates a new value expression */
ValExpr::ValExpr ( int _type, Term * _term ) :type ( _type )
{
//val_expr->type = _type;
term.constant = _term->constant;
term.param = _term->param;
}
//return val_expr;
ValExpr *ValExpr::create ( int _type , Term * _term )
{
if (_type == CONSTANT_TERM_T)
return new ConstantExpr( _type, _term );
else
return new ParameterExpr( _type, _term );
}
/* Creates a new general expression */
GenExpr::GenExpr ( int _type, void * _item ) :type ( _type ), item ( _item ) {}
GenExpr::GenExpr ( int _type, Expr * _item ) :type ( _type ), item ( _item ) {}
/* Frees a general expression */
GenExpr::~GenExpr()
{
switch ( type )
{
case VAL_T:
delete ( ( ValExpr* ) item );
break;
case PREFUN_T:
delete ( ( PrefunExpr* ) item );
break;
case TREE_T:
delete ( ( TreeExpr* ) item );
delete item;
break;
}
}

View File

@ -58,18 +58,27 @@ public:
Term() { this->constant = 0; this->param = 0; }
};
class Expr
{
public:
virtual ~Expr() {};
virtual bool isConstant(int mesh_i, int mesh_j) { return false; };
virtual float eval(int mesh_i, int mesh_j) = 0;
};
/* General Expression Type */
class GenExpr
class GenExpr : public Expr
{
public:
int type;
void * item;
Expr * item;
~GenExpr();
GenExpr( int type, void *item );
float eval_gen_expr(int mesh_i, int mesh_j);
GenExpr( int type, Expr *item );
float eval(int mesh_i, int mesh_j);
float eval_gen_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); }
static GenExpr *const_to_expr( float val );
static GenExpr *param_to_expr( Param *param );
@ -77,35 +86,41 @@ public:
};
/* Value expression, contains a term union */
class ValExpr
class ValExpr : public Expr
{
protected:
ValExpr( int type, Term *term );
public:
int type;
Term term;
static ValExpr *create( int type, Term *term );
~ValExpr();
ValExpr( int type, Term *term );
float eval_val_expr(int mesh_i, int mesh_j);
float eval_val_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); }
};
/* A binary expression tree ordered by operator precedence */
class TreeExpr
class TreeExpr : public Expr
{
private:
TreeExpr( InfixOp *infix_op, Expr *gen_expr,
TreeExpr *left, TreeExpr *right );
public:
static TreeExpr *create( InfixOp *infix_op, Expr *gen_expr,
TreeExpr *left, TreeExpr *right );
InfixOp * infix_op; /* null if leaf */
GenExpr * gen_expr;
Expr * gen_expr;
TreeExpr *left, *right;
~TreeExpr();
TreeExpr( InfixOp *infix_op, GenExpr *gen_expr,
TreeExpr *left, TreeExpr *right );
float eval_tree_expr(int mesh_i, int mesh_j);
float eval(int mesh_i, int mesh_j);
float eval_tree_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); }
};
/* A function expression in prefix form */
class PrefunExpr
class PrefunExpr : public Expr
{
public:
float (*func_ptr)(void*);
@ -115,8 +130,8 @@ public:
~PrefunExpr();
/* Evaluates functions in prefix form */
float eval_prefun_expr(int mesh_i, int mesh_j);
float eval(int mesh_i, int mesh_j);
float eval_prefun_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); }
};
#endif /** _EXPR_H */

View File

@ -999,7 +999,7 @@ TreeExpr * Parser::insert_infix_op(InfixOp * infix_op, TreeExpr **root)
if (*root == NULL)
{
new_root = new TreeExpr(infix_op, NULL, NULL, NULL);
new_root = TreeExpr::create(infix_op, NULL, NULL, NULL);
*root = new_root;
return new_root;
}
@ -1009,7 +1009,7 @@ TreeExpr * Parser::insert_infix_op(InfixOp * infix_op, TreeExpr **root)
if ((*root)->infix_op == NULL)
{
new_root = new TreeExpr(infix_op, NULL, *root, NULL);
new_root = TreeExpr::create(infix_op, NULL, *root, NULL);
(*root) = new_root;
return new_root;
}
@ -1020,7 +1020,7 @@ TreeExpr * Parser::insert_infix_op(InfixOp * infix_op, TreeExpr **root)
if (infix_op->precedence >= (*root)->infix_op->precedence)
{
new_root = new TreeExpr(infix_op, NULL, *root, NULL);
new_root = TreeExpr::create(infix_op, NULL, *root, NULL);
(*root) = new_root;
return new_root;
}
@ -1053,7 +1053,7 @@ TreeExpr * Parser::insert_gen_expr(GenExpr * gen_expr, TreeExpr ** root)
if (*root == NULL)
{
new_root = new TreeExpr(NULL, gen_expr, NULL, NULL);
new_root = TreeExpr::create(NULL, gen_expr, NULL, NULL);
*root = new_root;
return new_root;
}
@ -1085,7 +1085,7 @@ int Parser::insert_gen_rec(GenExpr * gen_expr, TreeExpr * root)
if ((root->left == NULL) && (root->infix_op != NULL))
{
root->left = new TreeExpr(NULL, gen_expr, NULL, NULL);
root->left = TreeExpr::create(NULL, gen_expr, NULL, NULL);
return PROJECTM_SUCCESS;
}
@ -1095,7 +1095,7 @@ int Parser::insert_gen_rec(GenExpr * gen_expr, TreeExpr * root)
if ((root->right == NULL) && (root->infix_op != NULL))
{
root->right = new TreeExpr(NULL, gen_expr, NULL, NULL);
root->right = TreeExpr::create(NULL, gen_expr, NULL, NULL);
return PROJECTM_SUCCESS;
}
@ -1131,14 +1131,14 @@ int Parser::insert_infix_rec(InfixOp * infix_op, TreeExpr * root)
I don't think this will ever happen */
if (root->left == NULL)
{
root->left = new TreeExpr(infix_op, NULL, root->left, NULL);
root->left = TreeExpr::create(infix_op, NULL, root->left, NULL);
return PROJECTM_SUCCESS;
}
/* Right tree is empty, attach this operator to it */
if (root->right == NULL)
{
root->right = new TreeExpr(infix_op, NULL, root->right, NULL);
root->right = TreeExpr::create(infix_op, NULL, root->right, NULL);
return PROJECTM_SUCCESS;
}
@ -1151,7 +1151,7 @@ int Parser::insert_infix_rec(InfixOp * infix_op, TreeExpr * root)
if (root->right->infix_op == NULL)
{
root->right = new TreeExpr(infix_op, NULL, root->right, NULL);
root->right = TreeExpr::create(infix_op, NULL, root->right, NULL);
return PROJECTM_SUCCESS;
}
@ -1162,7 +1162,7 @@ int Parser::insert_infix_rec(InfixOp * infix_op, TreeExpr * root)
/* Otherwise, insert the operator here */
root->right = new TreeExpr(infix_op, NULL, root->right, NULL);
root->right = TreeExpr::create(infix_op, NULL, root->right, NULL);
return PROJECTM_SUCCESS;
}
@ -1212,7 +1212,7 @@ GenExpr * Parser::parse_infix_op(std::istream & fs, token_t token, TreeExpr * t
case tRPr:
case tComma:
if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
gen_expr = new GenExpr(TREE_T, (void*)tree_expr);
gen_expr = new GenExpr(TREE_T, tree_expr);
assert(gen_expr);
return gen_expr;
default: