mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-03-30 03:03:53 +00:00
virtual Expr::eval()
This commit is contained in:
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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:
|
||||
|
||||
Reference in New Issue
Block a user