mirror of
https://github.com/projectM-visualizer/projectm.git
synced 2026-03-12 02:15:12 +00:00
Merge pull request #59 from mbellew/eval_perf
Expression evaluation performance
This commit is contained in:
@ -450,7 +450,7 @@ CustomWave::~CustomWave()
|
||||
|
||||
|
||||
// Comments: index is not passed, so we assume monotonic increment by 1 is ok here
|
||||
int CustomWave::add_per_point_eqn(char * name, GenExpr * gen_expr)
|
||||
int CustomWave::add_per_point_eqn(char * name, Expr * gen_expr)
|
||||
{
|
||||
|
||||
PerPointEqn * per_point_eqn;
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
#define CUSTOM_WAVE_DEBUG 0
|
||||
|
||||
class CustomWave;
|
||||
class GenExpr;
|
||||
class Expr;
|
||||
class PerPointEqn;
|
||||
class Preset;
|
||||
|
||||
@ -115,7 +115,7 @@ public:
|
||||
int per_frame_eqn_string_index;
|
||||
int per_frame_init_eqn_string_index;
|
||||
|
||||
int add_per_point_eqn(char * name, GenExpr * gen_expr);
|
||||
int add_per_point_eqn(char * name, Expr * gen_expr);
|
||||
void evalCustomWaveInitConditions(Preset *preset);
|
||||
|
||||
|
||||
|
||||
@ -69,25 +69,22 @@ public:
|
||||
*infix_negative,
|
||||
*infix_positive;
|
||||
|
||||
float eval_gen_expr(GenExpr * gen_expr);
|
||||
inline GenExpr * opt_gen_expr(GenExpr * gen_expr, int ** param_list);
|
||||
float eval_gen_expr(Expr * gen_expr);
|
||||
inline Expr * opt_gen_expr(Expr * gen_expr, int ** param_list);
|
||||
|
||||
GenExpr * const_to_expr(float val);
|
||||
GenExpr * param_to_expr(Param * param);
|
||||
GenExpr * prefun_to_expr(float (*func_ptr)(), GenExpr ** expr_list, int num_args);
|
||||
|
||||
static TreeExpr * new_tree_expr(InfixOp * infix_op, GenExpr * gen_expr, TreeExpr * left, TreeExpr * right);
|
||||
static GenExpr * new_gen_expr(int type, void * item);
|
||||
static ValExpr * new_val_expr(int type, Term *term);
|
||||
Expr * const_to_expr(float val);
|
||||
Expr * param_to_expr(Param * param);
|
||||
Expr * prefun_to_expr(float (*func_ptr)(), Expr ** expr_list, int num_args);
|
||||
|
||||
static TreeExpr * new_tree_expr(InfixOp * infix_op, Expr * gen_expr, TreeExpr * left, TreeExpr * right);
|
||||
static Expr * new_gen_expr(int type, void * item);
|
||||
|
||||
static InfixOp * new_infix_op(int type, int precedence);
|
||||
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);
|
||||
PrefunExpr * clone_prefun_expr(PrefunExpr * prefun_expr);
|
||||
};
|
||||
|
||||
|
||||
@ -27,40 +27,16 @@
|
||||
#include <iostream>
|
||||
#include "Eval.hpp"
|
||||
|
||||
float GenExpr::eval_gen_expr ( 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 );
|
||||
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];
|
||||
|
||||
float * arg_list;
|
||||
float * argp;
|
||||
GenExpr **expr_listp = expr_list;
|
||||
Expr **expr_listp = expr_list;
|
||||
|
||||
|
||||
if (this->num_args > 10) {
|
||||
@ -77,7 +53,7 @@ float PrefunExpr::eval_prefun_expr ( int mesh_i, int mesh_j )
|
||||
/* Evaluate each argument before calling the function itself */
|
||||
for ( int i = 0; i < num_args; i++ )
|
||||
{
|
||||
*(argp++) = (*(expr_listp++))->eval_gen_expr ( mesh_i, mesh_j );
|
||||
*(argp++) = (*(expr_listp++))->eval ( mesh_i, mesh_j );
|
||||
//printf("numargs %x", arg_list[i]);
|
||||
}
|
||||
/* Now we call the function, passing a list of
|
||||
@ -92,102 +68,243 @@ 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 )
|
||||
class PrefunExprOne : public PrefunExpr
|
||||
{
|
||||
|
||||
|
||||
/* Value is a constant, return the float value */
|
||||
if ( type == CONSTANT_TERM_T )
|
||||
float eval ( int mesh_i, int mesh_j )
|
||||
{
|
||||
return ( term.constant );
|
||||
float val = expr_list[0]->eval ( mesh_i, mesh_j );
|
||||
return (func_ptr)(&val);
|
||||
}
|
||||
};
|
||||
|
||||
/* Value is variable, dereference it */
|
||||
if ( type == PARAM_TERM_T )
|
||||
|
||||
class ConstantExpr : public Expr
|
||||
{
|
||||
float constant;
|
||||
public:
|
||||
ConstantExpr( float value ) : Expr(CONSTANT), constant(value) {}
|
||||
ConstantExpr( int type, Term *term ) : Expr(CONSTANT), constant(term->constant) {}
|
||||
bool isConstant()
|
||||
{
|
||||
switch ( term.param->type )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
float eval(int mesh_i, int mesh_j )
|
||||
{
|
||||
return constant;
|
||||
}
|
||||
std::ostream &to_string(std::ostream &out)
|
||||
{
|
||||
out << constant; return out;
|
||||
}
|
||||
};
|
||||
|
||||
case P_TYPE_BOOL:
|
||||
class ParameterExpr : public Expr
|
||||
{
|
||||
protected:
|
||||
Term term;
|
||||
public:
|
||||
ParameterExpr( int _type, Term *_term ) : Expr(PARAMETER), term(*_term) {}
|
||||
float eval(int mesh_i, int mesh_j );
|
||||
std::ostream& to_string(std::ostream& out)
|
||||
{
|
||||
out << term.param->name;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
class BoolParameterExpr : public ParameterExpr
|
||||
{
|
||||
public:
|
||||
BoolParameterExpr( int _type, Term *_term ) : ParameterExpr(_type,_term) {}
|
||||
float eval ( int mesh_i, int mesh_j ) { return ( float ) ( * ( ( bool* ) ( term.param->engine_val ) ) ); }
|
||||
};
|
||||
class IntParameterExpr : public ParameterExpr
|
||||
{
|
||||
public:
|
||||
IntParameterExpr( int _type, Term *_term ) : ParameterExpr(_type,_term) {}
|
||||
float eval ( int mesh_i, int mesh_j ) { return ( float ) ( * ( ( int* ) ( term.param->engine_val ) ) ); }
|
||||
};
|
||||
class FloatParameterExpr : public ParameterExpr
|
||||
{
|
||||
public:
|
||||
FloatParameterExpr( int _type, Term *_term ) : ParameterExpr(_type,_term) {}
|
||||
float eval ( int mesh_i, int mesh_j ) { return ( * ( ( float* ) ( term.param->engine_val ) ) ); }
|
||||
};
|
||||
|
||||
return ( float ) ( * ( ( bool* ) ( term.param->engine_val ) ) );
|
||||
case P_TYPE_INT:
|
||||
/* Evaluates a value expression */
|
||||
float ParameterExpr::eval ( int mesh_i, int mesh_j )
|
||||
{
|
||||
switch ( term.param->type )
|
||||
{
|
||||
case P_TYPE_BOOL:
|
||||
return ( float ) ( * ( ( bool* ) ( term.param->engine_val ) ) );
|
||||
case P_TYPE_INT:
|
||||
return ( float ) ( * ( ( int* ) ( term.param->engine_val ) ) );
|
||||
case P_TYPE_DOUBLE:
|
||||
if ( term.param->matrix_flag | ( term.param->flags & P_FLAG_ALWAYS_MATRIX ) )
|
||||
{
|
||||
|
||||
/* Sanity check the matrix is there... */
|
||||
assert ( term.param->matrix != NULL );
|
||||
|
||||
return ( float ) ( * ( ( int* ) ( term.param->engine_val ) ) );
|
||||
case P_TYPE_DOUBLE:
|
||||
|
||||
|
||||
if ( term.param->matrix_flag | ( term.param->flags & P_FLAG_ALWAYS_MATRIX ) )
|
||||
/// @slow boolean check could be expensive in this critical (and common) step of evaluation
|
||||
if ( mesh_i >= 0 )
|
||||
{
|
||||
|
||||
/* Sanity check the matrix is there... */
|
||||
assert ( term.param->matrix != NULL );
|
||||
|
||||
/// @slow boolean check could be expensive in this critical (and common) step of evaluation
|
||||
if ( mesh_i >= 0 )
|
||||
if ( mesh_j >= 0 )
|
||||
{
|
||||
if ( mesh_j >= 0 )
|
||||
{
|
||||
return ( ( ( float** ) term.param->matrix ) [mesh_i][mesh_j] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( ( ( float* ) term.param->matrix ) [mesh_i] );
|
||||
}
|
||||
return ( ( ( float** ) term.param->matrix ) [mesh_i][mesh_j] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ( ( ( float* ) term.param->matrix ) [mesh_i] );
|
||||
}
|
||||
//assert(mesh_i >=0);
|
||||
}
|
||||
//std::cout << term.param->name << ": " << (*((float*)term.param->engine_val)) << std::endl;
|
||||
return * ( ( float* ) ( term.param->engine_val ) );
|
||||
default:
|
||||
return EVAL_ERROR;
|
||||
}
|
||||
//assert(mesh_i >=0);
|
||||
}
|
||||
//std::cout << term.param->name << ": " << (*((float*)term.param->engine_val)) << std::endl;
|
||||
return * ( ( float* ) ( term.param->engine_val ) );
|
||||
default:
|
||||
return EVAL_ERROR;
|
||||
}
|
||||
/* Unknown type, return failure */
|
||||
return PROJECTM_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
class MultAndAddExpr : public Expr
|
||||
{
|
||||
Expr *a, *b, *c;
|
||||
public:
|
||||
MultAndAddExpr(Expr *_a, Expr *_b, Expr *_c) : Expr(OTHER),
|
||||
a(_a), b(_b), c(_c)
|
||||
{
|
||||
}
|
||||
float eval(int mesh_i, int mesh_j)
|
||||
{
|
||||
float a_value = a->eval(mesh_i,mesh_j);
|
||||
float b_value = b->eval(mesh_i,mesh_j);
|
||||
float c_value = c->eval(mesh_i,mesh_j);
|
||||
return a_value * b_value + c_value;
|
||||
}
|
||||
std::ostream &to_string(std::ostream &out)
|
||||
{
|
||||
out << "(" << a << " * " << b << ") + " << c;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
std::ostream &TreeExpr::to_string(std::ostream &out)
|
||||
{
|
||||
if (NULL == infix_op)
|
||||
{
|
||||
out << gen_expr;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "(" << left << " ";
|
||||
switch ( infix_op->type )
|
||||
{
|
||||
case INFIX_ADD:
|
||||
out << "+"; break;
|
||||
case INFIX_MINUS:
|
||||
out << "-"; break;
|
||||
case INFIX_MULT:
|
||||
out << "*"; break;
|
||||
case INFIX_MOD:
|
||||
out << "%"; break;
|
||||
case INFIX_OR:
|
||||
out << "|"; break;
|
||||
case INFIX_AND:
|
||||
out << "&"; break;
|
||||
case INFIX_DIV:
|
||||
out << "/"; break;
|
||||
default:
|
||||
out << "infix_op_ERROR"; break;
|
||||
}
|
||||
out << " " << right << ")";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* NOTE: Parser.cpp directly manipulates TreeExpr, so it is easier to optimizer AFTER parsing
|
||||
* than while building up the tree initially
|
||||
*/
|
||||
Expr *TreeExpr::optimize()
|
||||
{
|
||||
if (infix_op == NULL)
|
||||
{
|
||||
Expr *opt = gen_expr->optimize();
|
||||
if (opt != gen_expr)
|
||||
delete gen_expr;
|
||||
gen_expr = NULL;
|
||||
return opt;
|
||||
}
|
||||
if (left != NULL)
|
||||
{
|
||||
Expr *l = left->optimize();
|
||||
if (l != left)
|
||||
delete left;
|
||||
left = l;
|
||||
}
|
||||
if (right != NULL)
|
||||
{
|
||||
Expr *r = right->optimize();
|
||||
if (r != right)
|
||||
delete right;
|
||||
right = r;
|
||||
}
|
||||
if (left == NULL)
|
||||
{
|
||||
Expr *opt = right;
|
||||
right = NULL;
|
||||
return opt;
|
||||
}
|
||||
if (right == NULL)
|
||||
{
|
||||
Expr *opt = left;
|
||||
left = NULL;
|
||||
return opt;
|
||||
}
|
||||
if (left->isConstant() && right->isConstant())
|
||||
return Expr::const_to_expr(eval(-1, -1));
|
||||
|
||||
// this is gratuitious, but a*b+c is super common, so as proof-of-concept, let's make a special Expr
|
||||
if (infix_op->type == INFIX_ADD &&
|
||||
((left->clazz == TREE && ((TreeExpr *)left)->infix_op->type == INFIX_MULT) ||
|
||||
(right->clazz == TREE && ((TreeExpr *)right)->infix_op->type == INFIX_MULT)))
|
||||
{
|
||||
Expr *a, *b, *c;
|
||||
if (left->clazz == TREE && ((TreeExpr *)left)->infix_op->type == INFIX_MULT)
|
||||
{
|
||||
a = ((TreeExpr *)left)->left;
|
||||
b = ((TreeExpr *)left)->right;
|
||||
c = right;
|
||||
((TreeExpr *)left)->left = NULL;
|
||||
((TreeExpr *)left)->right = NULL;
|
||||
right = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
a = ((TreeExpr *)right)->left;
|
||||
b = ((TreeExpr *)right)->right;
|
||||
c = left;
|
||||
((TreeExpr *)right)->left = NULL;
|
||||
((TreeExpr *)right)->right = NULL;
|
||||
left = NULL;
|
||||
}
|
||||
return new MultAndAddExpr(a,b,c);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
}
|
||||
|
||||
/* 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 );
|
||||
/* shouldn't be null if we've called optimize() */
|
||||
assert(NULL != infix_op);
|
||||
|
||||
left_arg = left->eval ( mesh_i, mesh_j );
|
||||
right_arg = right->eval ( mesh_i, mesh_j );
|
||||
|
||||
switch ( infix_op->type )
|
||||
{
|
||||
@ -221,34 +338,16 @@ float TreeExpr::eval_tree_expr ( int mesh_i, int mesh_j )
|
||||
}
|
||||
|
||||
/* Converts a float value to a general expression */
|
||||
GenExpr * GenExpr::const_to_expr ( float val )
|
||||
Expr * Expr::const_to_expr ( float val )
|
||||
{
|
||||
|
||||
GenExpr * gen_expr;
|
||||
ValExpr * val_expr;
|
||||
Term term;
|
||||
|
||||
term.constant = val;
|
||||
|
||||
if ( ( val_expr = new ValExpr ( CONSTANT_TERM_T, &term ) ) == NULL )
|
||||
return NULL;
|
||||
|
||||
gen_expr = new GenExpr ( VAL_T, ( void* ) val_expr );
|
||||
|
||||
if ( gen_expr == NULL )
|
||||
{
|
||||
delete val_expr;
|
||||
}
|
||||
|
||||
return gen_expr;
|
||||
return new ConstantExpr( CONSTANT_TERM_T, &term );
|
||||
}
|
||||
|
||||
/* Converts a regular parameter to an expression */
|
||||
GenExpr * GenExpr::param_to_expr ( Param * param )
|
||||
Expr * Expr::param_to_expr ( Param * param )
|
||||
{
|
||||
|
||||
GenExpr * gen_expr = NULL;
|
||||
ValExpr * val_expr = NULL;
|
||||
Term term;
|
||||
|
||||
if ( param == NULL )
|
||||
@ -267,87 +366,93 @@ GenExpr * GenExpr::param_to_expr ( Param * param )
|
||||
making the parser handle the case where parameters are essentially per pixel equation
|
||||
substitutions */
|
||||
|
||||
|
||||
term.param = param;
|
||||
if ( ( val_expr = new ValExpr ( PARAM_TERM_T, &term ) ) == NULL )
|
||||
return NULL;
|
||||
|
||||
if ( ( gen_expr = new GenExpr ( VAL_T, ( void* ) val_expr ) ) == NULL )
|
||||
switch ( param->type )
|
||||
{
|
||||
delete val_expr;
|
||||
return NULL;
|
||||
case P_TYPE_BOOL:
|
||||
return new BoolParameterExpr( PARAM_TERM_T, &term );
|
||||
case P_TYPE_INT:
|
||||
return new IntParameterExpr( PARAM_TERM_T, &term );
|
||||
case P_TYPE_DOUBLE:
|
||||
// TODO are these flags constant??? can I check them now?
|
||||
if ( param->matrix_flag | ( param->flags & P_FLAG_ALWAYS_MATRIX ) )
|
||||
return new ParameterExpr( PARAM_TERM_T, &term );
|
||||
return new FloatParameterExpr( PARAM_TERM_T, &term );
|
||||
}
|
||||
return gen_expr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Converts a prefix function to an expression */
|
||||
GenExpr * GenExpr::prefun_to_expr ( float ( *func_ptr ) ( void * ), GenExpr ** expr_list, int num_args )
|
||||
Expr * Expr::prefun_to_expr ( float ( *func_ptr ) ( void * ), Expr ** expr_list, int num_args )
|
||||
{
|
||||
|
||||
GenExpr * gen_expr;
|
||||
PrefunExpr * prefun_expr;
|
||||
|
||||
prefun_expr = new PrefunExpr();
|
||||
|
||||
if ( prefun_expr == NULL )
|
||||
return NULL;
|
||||
|
||||
if (num_args == 1)
|
||||
prefun_expr = new PrefunExprOne();
|
||||
else
|
||||
prefun_expr = new PrefunExpr();
|
||||
prefun_expr->num_args = num_args;
|
||||
prefun_expr->func_ptr = ( float ( * ) ( void* ) ) func_ptr;
|
||||
prefun_expr->expr_list = expr_list;
|
||||
|
||||
gen_expr = new GenExpr ( PREFUN_T, ( void* ) prefun_expr );
|
||||
|
||||
if ( gen_expr == NULL )
|
||||
delete prefun_expr;
|
||||
|
||||
return gen_expr;
|
||||
return prefun_expr;
|
||||
}
|
||||
|
||||
/* 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 ) :
|
||||
Expr( TREE ),
|
||||
infix_op ( _infix_op ), gen_expr ( _gen_expr ),
|
||||
left ( _left ), right ( _right ) {}
|
||||
|
||||
|
||||
/* Creates a new value expression */
|
||||
ValExpr::ValExpr ( int _type, Term * _term ) :type ( _type )
|
||||
class TreeExprAdd : public TreeExpr
|
||||
{
|
||||
|
||||
|
||||
//val_expr->type = _type;
|
||||
term.constant = _term->constant;
|
||||
term.param = _term->param;
|
||||
|
||||
//return val_expr;
|
||||
}
|
||||
|
||||
/* Creates a new general expression */
|
||||
|
||||
GenExpr::GenExpr ( int _type, void * _item ) :type ( _type ), item ( _item ) {}
|
||||
|
||||
/* Frees a general expression */
|
||||
GenExpr::~GenExpr()
|
||||
{
|
||||
|
||||
switch ( type )
|
||||
public:
|
||||
TreeExprAdd( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, TreeExpr * _right ) :
|
||||
TreeExpr( _infix_op, _gen_expr, _left, _right) {}
|
||||
float eval( int mesh_i, int mesh_j)
|
||||
{
|
||||
case VAL_T:
|
||||
delete ( ( ValExpr* ) item );
|
||||
break;
|
||||
case PREFUN_T:
|
||||
delete ( ( PrefunExpr* ) item );
|
||||
break;
|
||||
case TREE_T:
|
||||
delete ( ( TreeExpr* ) item );
|
||||
break;
|
||||
return left->eval(mesh_i, mesh_j) + right->eval(mesh_i, mesh_j);
|
||||
}
|
||||
};
|
||||
|
||||
class TreeExprMinus : public TreeExpr
|
||||
{
|
||||
public:
|
||||
TreeExprMinus( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, TreeExpr * _right ) :
|
||||
TreeExpr( _infix_op, _gen_expr, _left, _right) {}
|
||||
float eval( int mesh_i, int mesh_j)
|
||||
{
|
||||
return left->eval(mesh_i, mesh_j) - right->eval(mesh_i, mesh_j);
|
||||
}
|
||||
};
|
||||
|
||||
class TreeExprMult : public TreeExpr
|
||||
{
|
||||
public:
|
||||
TreeExprMult( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, TreeExpr * _right ) :
|
||||
TreeExpr( _infix_op, _gen_expr, _left, _right) {}
|
||||
float eval( int mesh_i, int mesh_j)
|
||||
{
|
||||
return left->eval(mesh_i, mesh_j) * right->eval(mesh_i, mesh_j);
|
||||
}
|
||||
};
|
||||
|
||||
TreeExpr * TreeExpr::create( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, TreeExpr * _right )
|
||||
{
|
||||
if ( NULL != _infix_op )
|
||||
{
|
||||
if ( _infix_op->type == INFIX_ADD )
|
||||
return new TreeExprAdd( _infix_op, _gen_expr, _left, _right);
|
||||
if ( _infix_op->type == INFIX_MINUS )
|
||||
return new TreeExprMinus( _infix_op, _gen_expr, _left, _right);
|
||||
if ( _infix_op->type == INFIX_MULT )
|
||||
return new TreeExprMult( _infix_op, _gen_expr, _left, _right);
|
||||
}
|
||||
return new TreeExpr( _infix_op, _gen_expr, _left, _right );
|
||||
}
|
||||
|
||||
/* Frees a function in prefix notation */
|
||||
PrefunExpr::~PrefunExpr()
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
/* Free every element in expression list */
|
||||
@ -358,10 +463,6 @@ PrefunExpr::~PrefunExpr()
|
||||
free ( expr_list );
|
||||
}
|
||||
|
||||
/* Frees values of type VARIABLE and CONSTANT */
|
||||
ValExpr::~ValExpr()
|
||||
{}
|
||||
|
||||
/* Frees a tree expression */
|
||||
TreeExpr::~TreeExpr()
|
||||
{
|
||||
@ -390,13 +491,41 @@ TreeExpr::~TreeExpr()
|
||||
}
|
||||
|
||||
/* Initializes an infix operator */
|
||||
InfixOp::InfixOp ( int type, int precedence )
|
||||
InfixOp::InfixOp ( int _type, int _precedence )
|
||||
{
|
||||
|
||||
this->type = type;
|
||||
this->precedence = precedence;
|
||||
this->type = _type;
|
||||
this->precedence = _precedence;
|
||||
}
|
||||
|
||||
PrefunExpr::PrefunExpr() : Expr(FUNCTION)
|
||||
{
|
||||
}
|
||||
|
||||
Expr *PrefunExpr::optimize()
|
||||
{
|
||||
bool constant_args = true;
|
||||
for (int i=0 ; i < num_args ; i++)
|
||||
{
|
||||
Expr *orig = expr_list[i];
|
||||
expr_list[i] = orig->optimize();
|
||||
if (orig != expr_list[i])
|
||||
delete orig;
|
||||
constant_args &= expr_list[i]->isConstant();
|
||||
}
|
||||
// TODO most functions can be pre-evaluated if inputs are constant, but not all
|
||||
return this;
|
||||
}
|
||||
|
||||
PrefunExpr::PrefunExpr() {}
|
||||
std::ostream& PrefunExpr::to_string(std::ostream& out)
|
||||
{
|
||||
char comma = ' ';
|
||||
out << "<function>(";
|
||||
for (int i=0 ; i < num_args ; i++)
|
||||
{
|
||||
out << comma;
|
||||
out << expr_list[i];
|
||||
comma = ',';
|
||||
}
|
||||
out << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
|
||||
#include "dlldefs.h"
|
||||
#include "CValue.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class Param;
|
||||
|
||||
@ -58,65 +59,79 @@ public:
|
||||
|
||||
Term() { this->constant = 0; this->param = 0; }
|
||||
};
|
||||
|
||||
/* General Expression Type */
|
||||
class GenExpr
|
||||
{
|
||||
public:
|
||||
int type;
|
||||
void * item;
|
||||
|
||||
~GenExpr();
|
||||
|
||||
GenExpr( int type, void *item );
|
||||
float eval_gen_expr(int mesh_i, int mesh_j);
|
||||
|
||||
static GenExpr *const_to_expr( float val );
|
||||
static GenExpr *param_to_expr( Param *param );
|
||||
static GenExpr *prefun_to_expr( float (*func_ptr)(void *), GenExpr **expr_list, int num_args );
|
||||
|
||||
enum ExprClass
|
||||
{
|
||||
TREE, CONSTANT, PARAMETER, FUNCTION, OTHER
|
||||
};
|
||||
|
||||
/* Value expression, contains a term union */
|
||||
class ValExpr
|
||||
class Expr
|
||||
{
|
||||
public:
|
||||
int type;
|
||||
Term term;
|
||||
ExprClass clazz;
|
||||
Expr(ExprClass c) : clazz(c) {};
|
||||
virtual ~Expr() {};
|
||||
virtual Expr *optimize() { return this; };
|
||||
virtual bool isConstant() { return false; };
|
||||
virtual float eval(int mesh_i, int mesh_j) = 0;
|
||||
virtual std::ostream& to_string(std::ostream &out)
|
||||
{
|
||||
std::cout << "nyi"; return out;
|
||||
}
|
||||
|
||||
~ValExpr();
|
||||
ValExpr( int type, Term *term );
|
||||
|
||||
float eval_val_expr(int mesh_i, int mesh_j);
|
||||
static Expr *const_to_expr( float val );
|
||||
static Expr *param_to_expr( Param *param );
|
||||
static Expr *prefun_to_expr( float (*func_ptr)(void *), Expr **expr_list, int num_args );
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, Expr *expr)
|
||||
{
|
||||
if (NULL == expr)
|
||||
out << "NULL";
|
||||
else
|
||||
expr->to_string(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* A binary expression tree ordered by operator precedence */
|
||||
class TreeExpr
|
||||
class TreeExpr : public Expr
|
||||
{
|
||||
protected:
|
||||
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;
|
||||
TreeExpr *left, *right;
|
||||
Expr * gen_expr;
|
||||
// NOTE: before optimize() left and right will always be TreeExpr
|
||||
Expr *left, *right;
|
||||
// these are for type-safe access in Parser.cpp
|
||||
TreeExpr *&leftTree() { return *(TreeExpr **)&left; };
|
||||
TreeExpr *&rightTree() { return *(TreeExpr **)&right; };
|
||||
|
||||
~TreeExpr();
|
||||
TreeExpr( InfixOp *infix_op, GenExpr *gen_expr,
|
||||
TreeExpr *left, TreeExpr *right );
|
||||
|
||||
float eval_tree_expr(int mesh_i, int mesh_j);
|
||||
Expr *optimize();
|
||||
float eval(int mesh_i, int mesh_j);
|
||||
std::ostream& to_string(std::ostream &out);
|
||||
};
|
||||
|
||||
/* A function expression in prefix form */
|
||||
class PrefunExpr
|
||||
class PrefunExpr : public Expr
|
||||
{
|
||||
public:
|
||||
float (*func_ptr)(void*);
|
||||
int num_args;
|
||||
GenExpr **expr_list;
|
||||
Expr **expr_list;
|
||||
PrefunExpr();
|
||||
~PrefunExpr();
|
||||
|
||||
/* Evaluates functions in prefix form */
|
||||
float eval_prefun_expr(int mesh_i, int mesh_j);
|
||||
|
||||
Expr *optimize();
|
||||
float eval(int mesh_i, int mesh_j);
|
||||
std::ostream& to_string(std::ostream &out);
|
||||
};
|
||||
|
||||
#endif /** _EXPR_H */
|
||||
|
||||
@ -103,7 +103,7 @@ MilkdropPreset::~MilkdropPreset()
|
||||
/* Adds a per pixel equation according to its string name. This
|
||||
will be used only by the parser */
|
||||
|
||||
int MilkdropPreset::add_per_pixel_eqn(char * name, GenExpr * gen_expr)
|
||||
int MilkdropPreset::add_per_pixel_eqn(char * name, Expr * gen_expr)
|
||||
{
|
||||
|
||||
PerPixelEqn * per_pixel_eqn = NULL;
|
||||
|
||||
@ -95,7 +95,7 @@ public:
|
||||
|
||||
/// Used by parser
|
||||
/// @bug refactor
|
||||
int add_per_pixel_eqn( char *name, GenExpr *gen_expr );
|
||||
int add_per_pixel_eqn( char *name, Expr *gen_expr );
|
||||
|
||||
/// Accessor method to retrieve the absolute file path of the loaded MilkdropPreset
|
||||
/// \returns a file path string
|
||||
|
||||
@ -251,15 +251,15 @@ token_t Parser::parseToken(std::istream & fs, char * string)
|
||||
/* Parse input in the form of "exp, exp, exp, ...)"
|
||||
Returns a general expression list */
|
||||
|
||||
GenExpr **Parser::parse_prefix_args(std::istream & fs, int num_args, MilkdropPreset * preset)
|
||||
Expr **Parser::parse_prefix_args(std::istream & fs, int num_args, MilkdropPreset * preset)
|
||||
{
|
||||
|
||||
int i, j;
|
||||
GenExpr ** expr_list; /* List of arguments to function */
|
||||
GenExpr * gen_expr;
|
||||
Expr ** expr_list; /* List of arguments to function */
|
||||
Expr * gen_expr;
|
||||
|
||||
/* Malloc the expression list */
|
||||
expr_list = (GenExpr**)wipemalloc(sizeof(GenExpr*)*num_args);
|
||||
expr_list = (Expr**)wipemalloc(sizeof(Expr*)*num_args);
|
||||
|
||||
/* Malloc failed */
|
||||
if (expr_list == NULL)
|
||||
@ -331,7 +331,7 @@ int Parser::parse_per_pixel_eqn(std::istream & fs, MilkdropPreset * preset, cha
|
||||
|
||||
|
||||
char string[MAX_TOKEN_SIZE];
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
|
||||
|
||||
if (init_string != 0)
|
||||
@ -715,19 +715,17 @@ int Parser::parse_line(std::istream & fs, MilkdropPreset * preset)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Parses a general expression, this function is the meat of the parser */
|
||||
GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset)
|
||||
Expr * Parser::_parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset)
|
||||
{
|
||||
|
||||
int i;
|
||||
char string[MAX_TOKEN_SIZE];
|
||||
token_t token;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
float val;
|
||||
Param * param = NULL;
|
||||
Func * func;
|
||||
GenExpr ** expr_list;
|
||||
Expr ** expr_list;
|
||||
|
||||
switch (token = parseToken(fs,string))
|
||||
{
|
||||
@ -759,7 +757,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
}
|
||||
|
||||
/* Convert function to expression */
|
||||
if ((gen_expr = GenExpr::prefun_to_expr((float (*)(void *))func->func_ptr, expr_list, func->getNumArgs())) == NULL)
|
||||
if ((gen_expr = Expr::prefun_to_expr((float (*)(void *))func->func_ptr, expr_list, func->getNumArgs())) == NULL)
|
||||
{
|
||||
if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n",
|
||||
line_count);
|
||||
@ -818,7 +816,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
|
||||
|
||||
/* Treat prefix plus as implict 0 preceding operator */
|
||||
gen_expr = GenExpr::const_to_expr(0);
|
||||
gen_expr = Expr::const_to_expr(0);
|
||||
|
||||
return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);
|
||||
}
|
||||
@ -829,7 +827,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
{
|
||||
|
||||
/* Use the negative infix operator, but first add an implicit zero to the operator tree */
|
||||
gen_expr = GenExpr::const_to_expr(0);
|
||||
gen_expr = Expr::const_to_expr(0);
|
||||
//return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
|
||||
return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
|
||||
}
|
||||
@ -863,7 +861,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
/* CASE 1: Check if string is a just a floating point number */
|
||||
if (string_to_float(string, &val) != PROJECTM_PARSE_ERROR)
|
||||
{
|
||||
if ((gen_expr = GenExpr::const_to_expr(val)) == NULL)
|
||||
if ((gen_expr = Expr::const_to_expr(val)) == NULL)
|
||||
{
|
||||
if (tree_expr)
|
||||
delete tree_expr;
|
||||
@ -898,7 +896,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
|
||||
|
||||
/* Convert parameter to an expression */
|
||||
if ((gen_expr = GenExpr::param_to_expr(param)) == NULL)
|
||||
if ((gen_expr = Expr::param_to_expr(param)) == NULL)
|
||||
{
|
||||
delete tree_expr;
|
||||
return NULL;
|
||||
@ -932,7 +930,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
}
|
||||
|
||||
/* Convert parameter to an expression */
|
||||
if ((gen_expr = GenExpr::param_to_expr(param)) == NULL)
|
||||
if ((gen_expr = Expr::param_to_expr(param)) == NULL)
|
||||
{
|
||||
delete tree_expr;
|
||||
return NULL;
|
||||
@ -955,7 +953,7 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
}
|
||||
|
||||
/* Convert parameter to an expression */
|
||||
if ((gen_expr = GenExpr::param_to_expr(param)) == NULL)
|
||||
if ((gen_expr = Expr::param_to_expr(param)) == NULL)
|
||||
{
|
||||
delete tree_expr;
|
||||
return NULL;
|
||||
@ -981,6 +979,17 @@ GenExpr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Mil
|
||||
}
|
||||
|
||||
|
||||
Expr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset)
|
||||
{
|
||||
Expr *gen_expr = _parse_gen_expr( fs, tree_expr, preset );
|
||||
if (NULL == gen_expr)
|
||||
return NULL;
|
||||
//std::cout << gen_expr << std::endl;
|
||||
Expr *opt = gen_expr->optimize();
|
||||
//std::cout << opt << std::endl << std::endl;
|
||||
return opt;
|
||||
}
|
||||
|
||||
|
||||
/* Inserts expressions into tree according to operator precedence.
|
||||
If root is null, a new tree is created, with infix_op as only element */
|
||||
@ -999,7 +1008,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 +1018,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 +1029,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;
|
||||
}
|
||||
@ -1035,7 +1044,7 @@ TreeExpr * Parser::insert_infix_op(InfixOp * infix_op, TreeExpr **root)
|
||||
}
|
||||
|
||||
|
||||
TreeExpr * Parser::insert_gen_expr(GenExpr * gen_expr, TreeExpr ** root)
|
||||
TreeExpr * Parser::insert_gen_expr(Expr * gen_expr, TreeExpr ** root)
|
||||
{
|
||||
|
||||
TreeExpr * new_root;
|
||||
@ -1053,7 +1062,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;
|
||||
}
|
||||
@ -1067,7 +1076,7 @@ TreeExpr * Parser::insert_gen_expr(GenExpr * gen_expr, TreeExpr ** root)
|
||||
}
|
||||
|
||||
/* A recursive helper function to insert general expression elements into the operator tree */
|
||||
int Parser::insert_gen_rec(GenExpr * gen_expr, TreeExpr * root)
|
||||
int Parser::insert_gen_rec(Expr * gen_expr, TreeExpr * root)
|
||||
{
|
||||
|
||||
/* Trivial Case: root is null */
|
||||
@ -1085,7 +1094,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 +1104,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;
|
||||
}
|
||||
|
||||
@ -1103,8 +1112,8 @@ int Parser::insert_gen_rec(GenExpr * gen_expr, TreeExpr * root)
|
||||
this succeeds then return. If it fails, try
|
||||
recursing down to the right */
|
||||
|
||||
if (insert_gen_rec(gen_expr, root->left) == PROJECTM_FAILURE)
|
||||
return insert_gen_rec(gen_expr, root->right);
|
||||
if (insert_gen_rec(gen_expr, root->leftTree()) == PROJECTM_FAILURE)
|
||||
return insert_gen_rec(gen_expr, root->rightTree());
|
||||
|
||||
/* Impossible for control flow to reach here, but in
|
||||
the world of C programming, who knows... */
|
||||
@ -1131,14 +1140,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->leftTree(), 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->rightTree(), NULL);
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1149,29 +1158,29 @@ int Parser::insert_infix_rec(InfixOp * infix_op, TreeExpr * root)
|
||||
then insert the expression here, attaching the old right branch
|
||||
to the left of the new expression */
|
||||
|
||||
if (root->right->infix_op == NULL)
|
||||
if (root->rightTree()->infix_op == NULL)
|
||||
{
|
||||
root->right = new TreeExpr(infix_op, NULL, root->right, NULL);
|
||||
root->right = TreeExpr::create(infix_op, NULL, root->rightTree(), NULL);
|
||||
return PROJECTM_SUCCESS;
|
||||
}
|
||||
|
||||
/* Traverse deeper if the inserting operator precedence is less than the
|
||||
the root's right operator precedence */
|
||||
if (infix_op->precedence < root->right->infix_op->precedence)
|
||||
return insert_infix_rec(infix_op, root->right);
|
||||
if (infix_op->precedence < root->rightTree()->infix_op->precedence)
|
||||
return insert_infix_rec(infix_op, root->rightTree());
|
||||
|
||||
/* Otherwise, insert the operator here */
|
||||
|
||||
root->right = new TreeExpr(infix_op, NULL, root->right, NULL);
|
||||
root->right = TreeExpr::create(infix_op, NULL, root->rightTree(), NULL);
|
||||
return PROJECTM_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* Parses an infix operator */
|
||||
GenExpr * Parser::parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, MilkdropPreset * preset)
|
||||
Expr * Parser::parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, MilkdropPreset * preset)
|
||||
{
|
||||
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
|
||||
switch (token)
|
||||
{
|
||||
@ -1212,7 +1221,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 = tree_expr;
|
||||
assert(gen_expr);
|
||||
return gen_expr;
|
||||
default:
|
||||
@ -1358,7 +1367,7 @@ PerFrameEqn * Parser::parse_per_frame_eqn(std::istream & fs, int index, Milkdro
|
||||
char string[MAX_TOKEN_SIZE];
|
||||
Param * param;
|
||||
PerFrameEqn * per_frame_eqn;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
|
||||
|
||||
if (parseToken(fs, string) != tEq)
|
||||
@ -1408,7 +1417,7 @@ PerFrameEqn * Parser::parse_implicit_per_frame_eqn(std::istream & fs, char * pa
|
||||
|
||||
Param * param;
|
||||
PerFrameEqn * per_frame_eqn;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
|
||||
if (fs.fail())
|
||||
return NULL;
|
||||
@ -1558,7 +1567,7 @@ InitCond * Parser::parse_per_frame_init_eqn(std::istream & fs, MilkdropPreset *
|
||||
Param * param = NULL;
|
||||
CValue init_val;
|
||||
InitCond * init_cond;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
float val;
|
||||
token_t token;
|
||||
|
||||
@ -1604,7 +1613,7 @@ InitCond * Parser::parse_per_frame_init_eqn(std::istream & fs, MilkdropPreset *
|
||||
}
|
||||
|
||||
/* Compute initial condition value */
|
||||
val = gen_expr->eval_gen_expr(-1,-1);
|
||||
val = gen_expr->eval(-1,-1);
|
||||
|
||||
/* Free the general expression now that we are done with it */
|
||||
delete gen_expr;
|
||||
@ -2192,7 +2201,7 @@ int Parser::parse_wave_helper(std::istream & fs, MilkdropPreset * preset, int
|
||||
{
|
||||
|
||||
Param * param;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
char string[MAX_TOKEN_SIZE];
|
||||
PerFrameEqn * per_frame_eqn;
|
||||
CustomWave * custom_wave;
|
||||
@ -2458,7 +2467,7 @@ int Parser::parse_shape_per_frame_eqn(std::istream & fs, CustomShape * custom_sh
|
||||
{
|
||||
|
||||
Param * param;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
PerFrameEqn * per_frame_eqn;
|
||||
|
||||
char string[MAX_TOKEN_SIZE];
|
||||
@ -2520,7 +2529,7 @@ int Parser::parse_wave_per_frame_eqn(std::istream & fs, CustomWave * custom_wav
|
||||
{
|
||||
|
||||
Param * param;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
PerFrameEqn * per_frame_eqn;
|
||||
|
||||
char string[MAX_TOKEN_SIZE];
|
||||
|
||||
@ -122,7 +122,7 @@ typedef enum {
|
||||
|
||||
class CustomShape;
|
||||
class CustomWave;
|
||||
class GenExpr;
|
||||
class Expr;
|
||||
class InfixOp;
|
||||
class PerFrameEqn;
|
||||
class MilkdropPreset;
|
||||
@ -155,17 +155,17 @@ public:
|
||||
static int parse_line( std::istream & fs, MilkdropPreset * preset );
|
||||
|
||||
static int get_string_prefix_len(char * string);
|
||||
static TreeExpr * insert_gen_expr(GenExpr * gen_expr, TreeExpr ** root);
|
||||
static TreeExpr * insert_gen_expr(Expr * gen_expr, TreeExpr ** root);
|
||||
static TreeExpr * insert_infix_op(InfixOp * infix_op, TreeExpr ** root);
|
||||
static token_t parseToken(std::istream & fs, char * string);
|
||||
static GenExpr ** parse_prefix_args(std::istream & fs, int num_args, MilkdropPreset * preset);
|
||||
static GenExpr * parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, MilkdropPreset * preset);
|
||||
static GenExpr * parse_sign_arg(std::istream & fs);
|
||||
static Expr ** parse_prefix_args(std::istream & fs, int num_args, MilkdropPreset * preset);
|
||||
static Expr * parse_infix_op(std::istream & fs, token_t token, TreeExpr * tree_expr, MilkdropPreset * preset);
|
||||
static Expr * parse_sign_arg(std::istream & fs);
|
||||
static int parse_float(std::istream & fs, float * float_ptr);
|
||||
static int parse_int(std::istream & fs, int * int_ptr);
|
||||
static int insert_gen_rec(GenExpr * gen_expr, TreeExpr * root);
|
||||
static int insert_gen_rec(Expr * gen_expr, TreeExpr * root);
|
||||
static int insert_infix_rec(InfixOp * infix_op, TreeExpr * root);
|
||||
static GenExpr * parse_gen_expr(std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset);
|
||||
static Expr * parse_gen_expr(std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset);
|
||||
static PerFrameEqn * parse_implicit_per_frame_eqn(std::istream & fs, char * param_string, int index, MilkdropPreset * preset);
|
||||
static InitCond * parse_per_frame_init_eqn(std::istream & fs, MilkdropPreset * preset, std::map<std::string,Param*> * database);
|
||||
static int parse_wavecode_prefix(char * token, int * id, char ** var_string);
|
||||
@ -186,6 +186,8 @@ public:
|
||||
static int parse_shape_per_frame_eqn(std::istream & fs, CustomShape * custom_shape, MilkdropPreset * preset);
|
||||
static int parse_wave_per_frame_eqn(std::istream & fs, CustomWave * custom_wave, MilkdropPreset * preset);
|
||||
static bool wrapsToNextLine(const std::string & str);
|
||||
private:
|
||||
static Expr * _parse_gen_expr(std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset);
|
||||
};
|
||||
|
||||
#endif /** !_PARSER_H */
|
||||
|
||||
@ -43,10 +43,10 @@ void PerFrameEqn::evaluate() {
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
//*((float*)per_frame_eqn->param->engine_val) = eval_gen_expr(per_frame_eqn->gen_expr);
|
||||
//*((float*)per_frame_eqn->param->engine_val) = eval(per_frame_eqn->gen_expr);
|
||||
assert(gen_expr);
|
||||
assert(param);
|
||||
param->set_param(gen_expr->eval_gen_expr(-1,-1));
|
||||
param->set_param(gen_expr->eval(-1,-1));
|
||||
|
||||
if (PER_FRAME_EQN_DEBUG) printf(" = %.4f\n", *((float*)param->engine_val));
|
||||
|
||||
@ -63,5 +63,5 @@ PerFrameEqn::~PerFrameEqn() {
|
||||
}
|
||||
|
||||
/* Create a new per frame equation */
|
||||
PerFrameEqn::PerFrameEqn(int _index, Param * _param, GenExpr * _gen_expr) :
|
||||
PerFrameEqn::PerFrameEqn(int _index, Param * _param, Expr * _gen_expr) :
|
||||
index(_index), param(_param), gen_expr(_gen_expr) {}
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
|
||||
#define PER_FRAME_EQN_DEBUG 0
|
||||
|
||||
class GenExpr;
|
||||
class Expr;
|
||||
class Param;
|
||||
class PerFrameEqn;
|
||||
|
||||
@ -39,9 +39,9 @@ class PerFrameEqn {
|
||||
public:
|
||||
int index; /* a unique id for each per frame eqn (generated by order in preset files) */
|
||||
Param *param; /* parameter to be assigned a value */
|
||||
GenExpr *gen_expr; /* expression that paremeter is equal to */
|
||||
Expr *gen_expr; /* expression that paremeter is equal to */
|
||||
|
||||
PerFrameEqn(int index, Param * param, GenExpr * gen_expr);
|
||||
PerFrameEqn(int index, Param * param, Expr * gen_expr);
|
||||
~PerFrameEqn();
|
||||
|
||||
/// Evaluate the per frame equation
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
/* Evaluates a per pixel equation */
|
||||
void PerPixelEqn::evaluate(int mesh_i, int mesh_j) {
|
||||
|
||||
GenExpr * eqn_ptr = 0;
|
||||
Expr * eqn_ptr = 0;
|
||||
|
||||
|
||||
eqn_ptr = this->gen_expr;
|
||||
@ -47,13 +47,13 @@ void PerPixelEqn::evaluate(int mesh_i, int mesh_j) {
|
||||
|
||||
if (param_matrix == 0) {
|
||||
assert(param->engine_val);
|
||||
(*(float*)param->engine_val) = eqn_ptr->eval_gen_expr(mesh_i, mesh_j);
|
||||
(*(float*)param->engine_val) = eqn_ptr->eval(mesh_i, mesh_j);
|
||||
|
||||
} else {
|
||||
|
||||
assert(!(eqn_ptr == NULL || param_matrix == NULL));
|
||||
|
||||
param_matrix[mesh_i][mesh_j] = eqn_ptr->eval_gen_expr(mesh_i, mesh_j);
|
||||
param_matrix[mesh_i][mesh_j] = eqn_ptr->eval(mesh_i, mesh_j);
|
||||
|
||||
/* Now that this parameter has been referenced with a per
|
||||
pixel equation, we let the evaluator know by setting
|
||||
@ -64,7 +64,7 @@ void PerPixelEqn::evaluate(int mesh_i, int mesh_j) {
|
||||
}
|
||||
}
|
||||
|
||||
PerPixelEqn::PerPixelEqn(int _index, Param * _param, GenExpr * _gen_expr):index(_index), param(_param), gen_expr(_gen_expr) {
|
||||
PerPixelEqn::PerPixelEqn(int _index, Param * _param, Expr * _gen_expr):index(_index), param(_param), gen_expr(_gen_expr) {
|
||||
|
||||
assert(index >= 0);
|
||||
assert(param != 0);
|
||||
|
||||
@ -43,7 +43,7 @@
|
||||
#define WARP_OP 9
|
||||
#define NUM_OPS 10 /* obviously, this number is dependent on the number of existing per pixel operations */
|
||||
|
||||
class GenExpr;
|
||||
class Expr;
|
||||
class Param;
|
||||
class PerPixelEqn;
|
||||
class Preset;
|
||||
@ -53,13 +53,13 @@ public:
|
||||
int index; /* used for splay tree ordering. */
|
||||
int flags; /* primarily to specify if this variable is user-defined */
|
||||
Param *param;
|
||||
GenExpr *gen_expr;
|
||||
Expr *gen_expr;
|
||||
|
||||
void evalPerPixelEqns( Preset *preset );
|
||||
void evaluate(int mesh_i, int mesh_j);
|
||||
virtual ~PerPixelEqn();
|
||||
|
||||
PerPixelEqn(int index, Param * param, GenExpr * gen_expr);
|
||||
PerPixelEqn(int index, Param * param, Expr * gen_expr);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ void PerPointEqn::evaluate(int i)
|
||||
{
|
||||
|
||||
float * param_matrix;
|
||||
GenExpr * eqn_ptr;
|
||||
Expr * eqn_ptr;
|
||||
|
||||
// samples = CustomWave::interface_wave->samples;
|
||||
|
||||
@ -51,8 +51,7 @@ void PerPointEqn::evaluate(int i)
|
||||
if (param->matrix == NULL)
|
||||
{
|
||||
assert(param->matrix_flag == false);
|
||||
(*(float*)param->engine_val) = eqn_ptr->eval_gen_expr(i,-1);
|
||||
|
||||
(*(float*)param->engine_val) = eqn_ptr->eval(i,-1);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -62,7 +61,7 @@ void PerPointEqn::evaluate(int i)
|
||||
param_matrix = (float*)param->matrix;
|
||||
|
||||
// -1 is because per points only use one dimension
|
||||
param_matrix[i] = eqn_ptr->eval_gen_expr(i, -1);
|
||||
param_matrix[i] = eqn_ptr->eval(i, -1);
|
||||
|
||||
|
||||
/* Now that this parameter has been referenced with a per
|
||||
@ -76,7 +75,7 @@ void PerPointEqn::evaluate(int i)
|
||||
|
||||
}
|
||||
|
||||
PerPointEqn::PerPointEqn(int _index, Param * _param, GenExpr * _gen_expr, int _samples):
|
||||
PerPointEqn::PerPointEqn(int _index, Param * _param, Expr * _gen_expr, int _samples):
|
||||
index(_index),
|
||||
samples(_samples),
|
||||
param(_param),
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#define _PER_POINT_EQN_H
|
||||
|
||||
class CustomWave;
|
||||
class GenExpr;
|
||||
class Expr;
|
||||
class Param;
|
||||
class PerPointEqn;
|
||||
|
||||
@ -39,10 +39,10 @@ public:
|
||||
int index;
|
||||
int samples; // the number of samples to iterate over
|
||||
Param *param;
|
||||
GenExpr * gen_expr;
|
||||
Expr * gen_expr;
|
||||
~PerPointEqn();
|
||||
void evaluate(int i);
|
||||
PerPointEqn( int index, Param *param, GenExpr *gen_expr, int samples);
|
||||
PerPointEqn( int index, Param *param, Expr *gen_expr, int samples);
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user