From 6e4363d14624b63fc07bd42716a9c78bae5ef5bd Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Tue, 8 May 2018 21:56:22 -0700 Subject: [PATCH 1/8] virtual Expr::eval() --- .../MilkdropPresetFactory/Eval.hpp | 2 +- .../MilkdropPresetFactory/Expr.cpp | 123 ++++++++---------- .../MilkdropPresetFactory/Expr.hpp | 45 ++++--- .../MilkdropPresetFactory/Parser.cpp | 22 ++-- 4 files changed, 98 insertions(+), 94 deletions(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Eval.hpp b/src/libprojectM/MilkdropPresetFactory/Eval.hpp index 51bd22f7b..70da02546 100755 --- a/src/libprojectM/MilkdropPresetFactory/Eval.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Eval.hpp @@ -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); diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index 14b5ad1e6..27467a799 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -27,34 +27,25 @@ #include #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; } } diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.hpp b/src/libprojectM/MilkdropPresetFactory/Expr.hpp index b732531af..664c8512c 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.hpp @@ -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 */ diff --git a/src/libprojectM/MilkdropPresetFactory/Parser.cpp b/src/libprojectM/MilkdropPresetFactory/Parser.cpp index bf7c0f985..692d200c0 100755 --- a/src/libprojectM/MilkdropPresetFactory/Parser.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Parser.cpp @@ -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: From 2f8c3b6b7cc6202b250a68b30c1d6627b21adf2e Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Wed, 9 May 2018 08:43:05 -0700 Subject: [PATCH 2/8] kill GenExpr --- .../MilkdropPresetFactory/CustomWave.cpp | 2 +- .../MilkdropPresetFactory/CustomWave.hpp | 4 +- .../MilkdropPresetFactory/Eval.hpp | 16 +- .../MilkdropPresetFactory/Expr.cpp | 148 +++++------------- .../MilkdropPresetFactory/Expr.hpp | 16 +- .../MilkdropPresetFactory/MilkdropPreset.cpp | 2 +- .../MilkdropPresetFactory/MilkdropPreset.hpp | 2 +- .../MilkdropPresetFactory/Parser.cpp | 54 +++---- .../MilkdropPresetFactory/Parser.hpp | 14 +- .../MilkdropPresetFactory/PerFrameEqn.cpp | 6 +- .../MilkdropPresetFactory/PerFrameEqn.hpp | 6 +- .../MilkdropPresetFactory/PerPixelEqn.cpp | 8 +- .../MilkdropPresetFactory/PerPixelEqn.hpp | 6 +- .../MilkdropPresetFactory/PerPointEqn.cpp | 9 +- .../MilkdropPresetFactory/PerPointEqn.hpp | 6 +- 15 files changed, 114 insertions(+), 185 deletions(-) diff --git a/src/libprojectM/MilkdropPresetFactory/CustomWave.cpp b/src/libprojectM/MilkdropPresetFactory/CustomWave.cpp index 935cea745..c0cc8fbfd 100755 --- a/src/libprojectM/MilkdropPresetFactory/CustomWave.cpp +++ b/src/libprojectM/MilkdropPresetFactory/CustomWave.cpp @@ -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; diff --git a/src/libprojectM/MilkdropPresetFactory/CustomWave.hpp b/src/libprojectM/MilkdropPresetFactory/CustomWave.hpp index a951fedeb..f1df5aafa 100755 --- a/src/libprojectM/MilkdropPresetFactory/CustomWave.hpp +++ b/src/libprojectM/MilkdropPresetFactory/CustomWave.hpp @@ -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); diff --git a/src/libprojectM/MilkdropPresetFactory/Eval.hpp b/src/libprojectM/MilkdropPresetFactory/Eval.hpp index 70da02546..327145102 100755 --- a/src/libprojectM/MilkdropPresetFactory/Eval.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Eval.hpp @@ -69,15 +69,15 @@ 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); + 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, GenExpr * gen_expr, TreeExpr * left, TreeExpr * right); - static GenExpr * new_gen_expr(int type, void * item); + 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 ValExpr * new_val_expr(int type, Term *term); static InfixOp * new_infix_op(int type, int precedence); @@ -85,7 +85,7 @@ public: static int destroy_infix_ops(); void reset_engine_vars(); - GenExpr * clone_gen_expr(GenExpr * gen_expr); + Expr * clone_gen_expr(Expr * gen_expr); TreeExpr * clone_tree_expr(TreeExpr * tree_expr); ValExpr * clone_val_expr(ValExpr * val_expr); PrefunExpr * clone_prefun_expr(PrefunExpr * prefun_expr); diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index 27467a799..c1ed4c5ac 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -27,21 +27,6 @@ #include #include "Eval.hpp" -float GenExpr::eval ( int mesh_i, int mesh_j ) -{ - 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: - case PREFUN_T: - case TREE_T: - return item->eval( mesh_i, mesh_j ); - default: - return EVAL_ERROR; - } -} /* Evaluates functions in prefix form */ float PrefunExpr::eval ( int mesh_i, int mesh_j ) @@ -51,7 +36,7 @@ float PrefunExpr::eval ( int mesh_i, int mesh_j ) float * arg_list; float * argp; - GenExpr **expr_listp = expr_list; + Expr **expr_listp = expr_list; if (this->num_args > 10) { @@ -68,7 +53,7 @@ float PrefunExpr::eval ( 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 @@ -100,47 +85,47 @@ public: /* Evaluates a value expression */ float ParameterExpr::eval ( int mesh_i, int mesh_j ) +{ + switch ( term.param->type ) { - switch ( term.param->type ) - { - case P_TYPE_BOOL: + case P_TYPE_BOOL: - return ( float ) ( * ( ( bool* ) ( term.param->engine_val ) ) ); - case P_TYPE_INT: + return ( float ) ( * ( ( bool* ) ( term.param->engine_val ) ) ); + case P_TYPE_INT: - return ( float ) ( * ( ( int* ) ( term.param->engine_val ) ) ); - case P_TYPE_DOUBLE: + return ( float ) ( * ( ( int* ) ( term.param->engine_val ) ) ); + case P_TYPE_DOUBLE: - if ( term.param->matrix_flag | ( term.param->flags & P_FLAG_ALWAYS_MATRIX ) ) + if ( term.param->matrix_flag | ( term.param->flags & P_FLAG_ALWAYS_MATRIX ) ) + { + + /* 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 ) { - - /* 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; } +} /* This could be optimized a lot more if we could return an Expr instead of a TreeExpr */ @@ -151,14 +136,14 @@ TreeExpr * TreeExpr::create( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _ if (_infix_op == NULL) { if (_gen_expr == NULL) - _gen_expr = GenExpr::const_to_expr(0.0f); + _gen_expr = Expr::const_to_expr(0.0f); } else { if (_left == NULL) - _left = new TreeExpr(NULL, GenExpr::const_to_expr(defautFloat), NULL, NULL); + _left = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); if (_right == NULL) - _right = new TreeExpr(NULL, GenExpr::const_to_expr(defautFloat), NULL, NULL); + _right = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); } return new TreeExpr( _infix_op, _gen_expr, _left, _right); } @@ -212,33 +197,16 @@ float TreeExpr::eval ( 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 = ValExpr::create( CONSTANT_TERM_T, &term ) ) == NULL ) - return NULL; - - gen_expr = new GenExpr ( VAL_T, val_expr ); - - if ( gen_expr == NULL ) - { - delete val_expr; - } - - return gen_expr; + return ValExpr::create( 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; @@ -260,39 +228,19 @@ GenExpr * GenExpr::param_to_expr ( Param * param ) term.param = param; - if ( ( val_expr = ValExpr::create( PARAM_TERM_T, &term ) ) == NULL ) - return NULL; - - if ( ( gen_expr = new GenExpr ( VAL_T, val_expr ) ) == NULL ) - { - delete val_expr; - return NULL; - } - return gen_expr; + return ValExpr::create( PARAM_TERM_T, &term ); } /* 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; - 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, prefun_expr ); - - if ( gen_expr == NULL ) - delete prefun_expr; - - return gen_expr; + return prefun_expr; } /* Creates a new tree expression */ @@ -316,27 +264,9 @@ ValExpr *ValExpr::create ( int _type , Term * _term ) return new ParameterExpr( _type, _term ); } -/* Creates a new general expression */ - -GenExpr::GenExpr ( int _type, Expr * _item ) :type ( _type ), item ( _item ) {} - -/* Frees a general expression */ -GenExpr::~GenExpr() -{ - switch ( type ) - { - case VAL_T: - case PREFUN_T: - case TREE_T: - delete item; - break; - } -} - /* Frees a function in prefix notation */ PrefunExpr::~PrefunExpr() { - int i; /* Free every element in expression list */ diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.hpp b/src/libprojectM/MilkdropPresetFactory/Expr.hpp index 664c8512c..2d0b289b6 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.hpp @@ -65,10 +65,14 @@ public: virtual ~Expr() {}; virtual bool isConstant(int mesh_i, int mesh_j) { return false; }; virtual float eval(int mesh_i, int mesh_j) = 0; + + 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 ); }; -/* General Expression Type */ -class GenExpr : public Expr +/* General Expression Type +class GenExpr : public GenExpr { public: int type; @@ -79,11 +83,7 @@ public: 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 ); - static GenExpr *prefun_to_expr( float (*func_ptr)(void *), GenExpr **expr_list, int num_args ); -}; + }; */ /* Value expression, contains a term union */ class ValExpr : public Expr @@ -125,7 +125,7 @@ class PrefunExpr : public Expr public: float (*func_ptr)(void*); int num_args; - GenExpr **expr_list; + Expr **expr_list; PrefunExpr(); ~PrefunExpr(); diff --git a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp index 304ce7039..bd94f6f46 100755 --- a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp +++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.cpp @@ -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; diff --git a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp index 89fc7f89a..87cb0ee89 100644 --- a/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp +++ b/src/libprojectM/MilkdropPresetFactory/MilkdropPreset.hpp @@ -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 diff --git a/src/libprojectM/MilkdropPresetFactory/Parser.cpp b/src/libprojectM/MilkdropPresetFactory/Parser.cpp index 692d200c0..c089add16 100755 --- a/src/libprojectM/MilkdropPresetFactory/Parser.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Parser.cpp @@ -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) @@ -717,17 +717,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 +759,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 +818,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 +829,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 +863,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 +898,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 +932,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 +955,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; @@ -1035,7 +1035,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; @@ -1067,7 +1067,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 */ @@ -1168,10 +1168,10 @@ int Parser::insert_infix_rec(InfixOp * infix_op, TreeExpr * root) } /* 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 +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, tree_expr); + gen_expr = tree_expr; assert(gen_expr); return gen_expr; default: @@ -1358,7 +1358,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 +1408,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 +1558,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 +1604,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 +2192,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 +2458,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 +2520,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]; diff --git a/src/libprojectM/MilkdropPresetFactory/Parser.hpp b/src/libprojectM/MilkdropPresetFactory/Parser.hpp index 6c28a551e..8809192bb 100755 --- a/src/libprojectM/MilkdropPresetFactory/Parser.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Parser.hpp @@ -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 * database); static int parse_wavecode_prefix(char * token, int * id, char ** var_string); diff --git a/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.cpp b/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.cpp index 30e23422b..4d4efb856 100755 --- a/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.cpp +++ b/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.cpp @@ -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) {} diff --git a/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.hpp b/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.hpp index 39640805d..4b703acb8 100755 --- a/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.hpp +++ b/src/libprojectM/MilkdropPresetFactory/PerFrameEqn.hpp @@ -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 diff --git a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp index 3f7c7bdcc..b32324596 100755 --- a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp +++ b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.cpp @@ -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); diff --git a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp index 9410d7620..e991c7c1c 100755 --- a/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp +++ b/src/libprojectM/MilkdropPresetFactory/PerPixelEqn.hpp @@ -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); }; diff --git a/src/libprojectM/MilkdropPresetFactory/PerPointEqn.cpp b/src/libprojectM/MilkdropPresetFactory/PerPointEqn.cpp index e921916db..60bfb0ed5 100755 --- a/src/libprojectM/MilkdropPresetFactory/PerPointEqn.cpp +++ b/src/libprojectM/MilkdropPresetFactory/PerPointEqn.cpp @@ -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), diff --git a/src/libprojectM/MilkdropPresetFactory/PerPointEqn.hpp b/src/libprojectM/MilkdropPresetFactory/PerPointEqn.hpp index 90ba5ca1c..17838a492 100755 --- a/src/libprojectM/MilkdropPresetFactory/PerPointEqn.hpp +++ b/src/libprojectM/MilkdropPresetFactory/PerPointEqn.hpp @@ -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); }; From 96a76ad1edb7628a856ab08825367395c6ae03d2 Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Wed, 9 May 2018 22:39:02 -0700 Subject: [PATCH 3/8] optimize() --- .../MilkdropPresetFactory/Eval.hpp | 5 +- .../MilkdropPresetFactory/Expr.cpp | 218 ++++++++++++++---- .../MilkdropPresetFactory/Expr.hpp | 54 ++--- .../MilkdropPresetFactory/Parser.cpp | 31 ++- .../MilkdropPresetFactory/Parser.hpp | 2 + 5 files changed, 216 insertions(+), 94 deletions(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Eval.hpp b/src/libprojectM/MilkdropPresetFactory/Eval.hpp index 327145102..7bf67287d 100755 --- a/src/libprojectM/MilkdropPresetFactory/Eval.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Eval.hpp @@ -78,16 +78,13 @@ public: 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 ValExpr * new_val_expr(int type, Term *term); - + static InfixOp * new_infix_op(int type, int precedence); static int init_infix_ops(); static int destroy_infix_ops(); void reset_engine_vars(); - Expr * clone_gen_expr(Expr * gen_expr); TreeExpr * clone_tree_expr(TreeExpr * tree_expr); - ValExpr * clone_val_expr(ValExpr * val_expr); PrefunExpr * clone_prefun_expr(PrefunExpr * prefun_expr); }; diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index c1ed4c5ac..8c4dc5de7 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -68,19 +68,57 @@ float PrefunExpr::eval ( int mesh_i, int mesh_j ) } -// private subclasses of ValExpr -- ConstantExpr, ParameterExpr -class ConstantExpr : public ValExpr +class ConstantExpr : public Expr { + float constant; public: - ConstantExpr( int type, Term *term ) : ValExpr(type,term) {} - float eval(int mesh_i, int mesh_j ) { return term.constant; } + ConstantExpr( float constant ) : constant(constant) {} + ConstantExpr( int type, Term *term ) : constant(term->constant) {} + bool isConstant() + { + return true; + } + float eval(int mesh_i, int mesh_j ) + { + return constant; + } + std::ostream &to_string(std::ostream &out) + { + out << constant; return out; + } }; -class ParameterExpr : public ValExpr +class ParameterExpr : public Expr +{ +protected: + Term term; +public: + ParameterExpr( int type, Term *term ) : 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: - ParameterExpr( int type, Term *term ) : ValExpr(type,term) {} - float eval(int mesh_i, int mesh_j ); + 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 ) ) ); } }; /* Evaluates a value expression */ @@ -88,18 +126,11 @@ 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 ) ) { @@ -131,21 +162,94 @@ float ParameterExpr::eval ( int mesh_i, int mesh_j ) /* 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; + // float defautFloat = _infix_op == Eval::infix_mult ? 1.0f : 0.0f; - if (_infix_op == NULL) + // if (_infix_op == NULL) + // { + // if (_gen_expr == NULL) + // _gen_expr = Expr::const_to_expr(0.0f); + // } + // else + // { + // if (_left == NULL) + // _left = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); + // if (_right == NULL) + // _right = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); + // } + return new TreeExpr( _infix_op, _gen_expr, _left, _right); +} + +std::ostream &TreeExpr::to_string(std::ostream &out) +{ + if (NULL == infix_op) { - if (_gen_expr == NULL) - _gen_expr = Expr::const_to_expr(0.0f); + out << gen_expr; } else { - if (_left == NULL) - _left = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); - if (_right == NULL) - _right = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); + 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 new TreeExpr( _infix_op, _gen_expr, _left, _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) + { + left = new TreeExpr(NULL, Expr::const_to_expr(infix_op == Eval::infix_mult ? 1.0f : 0.0f), NULL, NULL); + } + else + { + Expr *l = left->optimize(); + if (l != left) + delete left; + left = l; + } + if (right == NULL) + { + right = new TreeExpr(NULL, Expr::const_to_expr(infix_op == Eval::infix_mult ? 1.0f : 0.0f), NULL, NULL); + } + else + { + Expr *r = right->optimize(); + if (r != right) + delete right; + right = r; + } + if (left->isConstant() && right->isConstant()) + return Expr::const_to_expr(eval(0.5, 0.5)); + return this; } /* Evaluates an expression tree */ @@ -201,13 +305,12 @@ Expr * Expr::const_to_expr ( float val ) { Term term; term.constant = val; - return ValExpr::create( CONSTANT_TERM_T, &term ); + return new ConstantExpr( CONSTANT_TERM_T, &term ); } /* Converts a regular parameter to an expression */ Expr * Expr::param_to_expr ( Param * param ) { - ValExpr * val_expr = NULL; Term term; if ( param == NULL ) @@ -226,9 +329,21 @@ Expr * Expr::param_to_expr ( Param * param ) making the parser handle the case where parameters are essentially per pixel equation substitutions */ - term.param = param; - return ValExpr::create( PARAM_TERM_T, &term ); + + switch ( param->type ) + { + 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 NULL; } /* Converts a prefix function to an expression */ @@ -249,21 +364,6 @@ TreeExpr::TreeExpr ( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, Tr left ( _left ), right ( _right ) {} -/* Creates a new value expression */ -ValExpr::ValExpr ( int _type, Term * _term ) :type ( _type ) -{ - term.constant = _term->constant; - term.param = _term->param; -} - -ValExpr *ValExpr::create ( int _type , Term * _term ) -{ - if (_type == CONSTANT_TERM_T) - return new ConstantExpr( _type, _term ); - else - return new ParameterExpr( _type, _term ); -} - /* Frees a function in prefix notation */ PrefunExpr::~PrefunExpr() { @@ -277,10 +377,6 @@ PrefunExpr::~PrefunExpr() free ( expr_list ); } -/* Frees values of type VARIABLE and CONSTANT */ -ValExpr::~ValExpr() -{} - /* Frees a tree expression */ TreeExpr::~TreeExpr() { @@ -311,7 +407,6 @@ TreeExpr::~TreeExpr() /* Initializes an infix operator */ InfixOp::InfixOp ( int type, int precedence ) { - this->type = type; this->precedence = precedence; } @@ -319,3 +414,32 @@ InfixOp::InfixOp ( int type, int precedence ) PrefunExpr::PrefunExpr() {} + +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; +} + +std::ostream& PrefunExpr::to_string(std::ostream& out) +{ + char *comma = ""; + out << "("; + for (int i=0 ; i < num_args ; i++) + { + out << comma; + out << expr_list[i]; + comma = ","; + } + out << ")"; + return out; +} diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.hpp b/src/libprojectM/MilkdropPresetFactory/Expr.hpp index 2d0b289b6..01d41bb49 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.hpp @@ -31,6 +31,7 @@ #include "dlldefs.h" #include "CValue.hpp" +#include class Param; @@ -63,42 +64,27 @@ class Expr { public: virtual ~Expr() {}; - virtual bool isConstant(int mesh_i, int mesh_j) { return false; }; + 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; + } 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 ); }; -/* General Expression Type -class GenExpr : public GenExpr +inline std::ostream& operator<<(std::ostream& out, Expr *expr) { -public: - int type; - Expr * item; - - ~GenExpr(); - - 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); } - }; */ - -/* Value expression, contains a term union */ -class ValExpr : public Expr -{ -protected: - ValExpr( int type, Term *term ); -public: - int type; - Term term; - - static ValExpr *create( int type, Term *term ); - ~ValExpr(); - - float eval_val_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); } -}; + if (NULL == expr) + out << "NULL"; + else + expr->to_string(out); + return out; +} /* A binary expression tree ordered by operator precedence */ class TreeExpr : public Expr @@ -111,12 +97,17 @@ public: TreeExpr *left, TreeExpr *right ); InfixOp * infix_op; /* null if leaf */ Expr * gen_expr; - TreeExpr *left, *right; + // 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(); + Expr *optimize(); float eval(int mesh_i, int mesh_j); - float eval_tree_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); } + std::ostream& to_string(std::ostream &out); }; /* A function expression in prefix form */ @@ -130,8 +121,9 @@ public: ~PrefunExpr(); /* Evaluates functions in prefix form */ + Expr *optimize(); float eval(int mesh_i, int mesh_j); - float eval_prefun_expr(int mesh_i, int mesh_j) { return eval(mesh_i, mesh_j); } + std::ostream& to_string(std::ostream &out); }; #endif /** _EXPR_H */ diff --git a/src/libprojectM/MilkdropPresetFactory/Parser.cpp b/src/libprojectM/MilkdropPresetFactory/Parser.cpp index c089add16..3859d1ba6 100755 --- a/src/libprojectM/MilkdropPresetFactory/Parser.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Parser.cpp @@ -715,11 +715,9 @@ int Parser::parse_line(std::istream & fs, MilkdropPreset * preset) } - /* Parses a general expression, this function is the meat of the parser */ -Expr * 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; @@ -981,6 +979,15 @@ Expr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Milkdr } +Expr * Parser::parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, MilkdropPreset * preset) +{ + Expr *gen_expr = _parse_gen_expr( fs, tree_expr, preset ); + //std::cout << gen_expr << std::endl; + Expr *opt = gen_expr->optimize(); + //std::cout << opt << 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 */ @@ -1103,8 +1110,8 @@ int Parser::insert_gen_rec(Expr * 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 +1138,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 = TreeExpr::create(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 = TreeExpr::create(infix_op, NULL, root->right, NULL); + root->right = TreeExpr::create(infix_op, NULL, root->rightTree(), NULL); return PROJECTM_SUCCESS; } @@ -1149,20 +1156,20 @@ 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 = TreeExpr::create(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 = TreeExpr::create(infix_op, NULL, root->right, NULL); + root->right = TreeExpr::create(infix_op, NULL, root->rightTree(), NULL); return PROJECTM_SUCCESS; } diff --git a/src/libprojectM/MilkdropPresetFactory/Parser.hpp b/src/libprojectM/MilkdropPresetFactory/Parser.hpp index 8809192bb..b52fede6d 100755 --- a/src/libprojectM/MilkdropPresetFactory/Parser.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Parser.hpp @@ -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 */ From f5e83537f73143ebb3eefc6282552810066caaf8 Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Thu, 10 May 2018 14:50:37 -0700 Subject: [PATCH 4/8] ExprClass and some warning cleanup --- .../MilkdropPresetFactory/Expr.cpp | 128 +++++++++++------- .../MilkdropPresetFactory/Expr.hpp | 8 ++ 2 files changed, 89 insertions(+), 47 deletions(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index 8c4dc5de7..67f3f5585 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -72,8 +72,8 @@ class ConstantExpr : public Expr { float constant; public: - ConstantExpr( float constant ) : constant(constant) {} - ConstantExpr( int type, Term *term ) : constant(term->constant) {} + ConstantExpr( float value ) : Expr(CONSTANT), constant(value) {} + ConstantExpr( int type, Term *term ) : Expr(CONSTANT), constant(term->constant) {} bool isConstant() { return true; @@ -93,7 +93,7 @@ class ParameterExpr : public Expr protected: Term term; public: - ParameterExpr( int type, Term *term ) : term(*term) {} + ParameterExpr( int _type, Term *_term ) : Expr(PARAMETER), term(*_term) {} float eval(int mesh_i, int mesh_j ); std::ostream& to_string(std::ostream& out) { @@ -105,19 +105,19 @@ public: class BoolParameterExpr : public ParameterExpr { public: - BoolParameterExpr( int type, Term *term ) : ParameterExpr(type,term) {} + 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) {} + 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) {} + FloatParameterExpr( int _type, Term *_term ) : ParameterExpr(_type,_term) {} float eval ( int mesh_i, int mesh_j ) { return ( * ( ( float* ) ( term.param->engine_val ) ) ); } }; @@ -159,23 +159,31 @@ float ParameterExpr::eval ( int mesh_i, int mesh_j ) } +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; + } +}; + /* 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 = Expr::const_to_expr(0.0f); - // } - // else - // { - // if (_left == NULL) - // _left = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); - // if (_right == NULL) - // _right = new TreeExpr(NULL, Expr::const_to_expr(defautFloat), NULL, NULL); - // } return new TreeExpr( _infix_op, _gen_expr, _left, _right); } @@ -225,30 +233,61 @@ Expr *TreeExpr::optimize() gen_expr = NULL; return opt; } - if (left == NULL) - { - left = new TreeExpr(NULL, Expr::const_to_expr(infix_op == Eval::infix_mult ? 1.0f : 0.0f), NULL, NULL); - } - else + if (left != NULL) { Expr *l = left->optimize(); if (l != left) delete left; left = l; } - if (right == NULL) - { - right = new TreeExpr(NULL, Expr::const_to_expr(infix_op == Eval::infix_mult ? 1.0f : 0.0f), NULL, NULL); - } - else + 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(0.5, 0.5)); + 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; } @@ -257,14 +296,8 @@ 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 ) - { - return gen_expr->eval( mesh_i, mesh_j ); - } - - /* Otherwise, this node is an infix operator. Evaluate - accordingly */ + /* 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 ); @@ -360,6 +393,7 @@ Expr * Expr::prefun_to_expr ( float ( *func_ptr ) ( void * ), Expr ** expr_list, /* Creates a new tree expression */ 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 ) {} @@ -405,15 +439,15 @@ 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() {} +PrefunExpr::PrefunExpr() : Expr(FUNCTION) +{ +} Expr *PrefunExpr::optimize() { @@ -432,13 +466,13 @@ Expr *PrefunExpr::optimize() std::ostream& PrefunExpr::to_string(std::ostream& out) { - char *comma = ""; + char comma = ' '; out << "("; for (int i=0 ; i < num_args ; i++) { out << comma; out << expr_list[i]; - comma = ","; + comma = ','; } out << ")"; return out; diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.hpp b/src/libprojectM/MilkdropPresetFactory/Expr.hpp index 01d41bb49..2aa5c97c2 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.hpp @@ -60,9 +60,17 @@ public: Term() { this->constant = 0; this->param = 0; } }; + +enum ExprClass +{ + TREE, CONSTANT, PARAMETER, FUNCTION, OTHER +}; + class Expr { public: + ExprClass clazz; + Expr(ExprClass c) : clazz(c) {}; virtual ~Expr() {}; virtual Expr *optimize() { return this; }; virtual bool isConstant() { return false; }; From f4a29d54fe6a2156dde2988b9e79aeda782171a6 Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Thu, 10 May 2018 18:47:15 -0700 Subject: [PATCH 5/8] PrefunExprOne --- src/libprojectM/MilkdropPresetFactory/Expr.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index 67f3f5585..2300f4e8f 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -68,6 +68,16 @@ float PrefunExpr::eval ( int mesh_i, int mesh_j ) } +class PrefunExprOne : public PrefunExpr +{ + float eval ( int mesh_i, int mesh_j ) + { + float val = expr_list[0]->eval ( mesh_i, mesh_j ); + return (func_ptr)(&val); + } +}; + + class ConstantExpr : public Expr { float constant; @@ -383,8 +393,10 @@ Expr * Expr::param_to_expr ( Param * param ) Expr * Expr::prefun_to_expr ( float ( *func_ptr ) ( void * ), Expr ** expr_list, int num_args ) { PrefunExpr * prefun_expr; - - prefun_expr = new PrefunExpr(); + 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; From 10b0a4d9a4ac9bf90274fc5cc138e4f8fd672e35 Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Thu, 10 May 2018 19:30:28 -0700 Subject: [PATCH 6/8] TreeExprMult --- .../MilkdropPresetFactory/Expr.cpp | 52 ++++++++++++++++--- .../MilkdropPresetFactory/Expr.hpp | 2 +- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index 2300f4e8f..cf58b1b95 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -191,12 +191,6 @@ public: } }; -/* 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 ) -{ - return new TreeExpr( _infix_op, _gen_expr, _left, _right); -} - std::ostream &TreeExpr::to_string(std::ostream &out) { if (NULL == infix_op) @@ -409,6 +403,52 @@ TreeExpr::TreeExpr ( InfixOp * _infix_op, Expr * _gen_expr, TreeExpr * _left, Tr infix_op ( _infix_op ), gen_expr ( _gen_expr ), left ( _left ), right ( _right ) {} +class TreeExprAdd : public TreeExpr +{ +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) + { + 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() diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.hpp b/src/libprojectM/MilkdropPresetFactory/Expr.hpp index 2aa5c97c2..a1eb006d4 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.hpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.hpp @@ -97,7 +97,7 @@ inline std::ostream& operator<<(std::ostream& out, Expr *expr) /* A binary expression tree ordered by operator precedence */ class TreeExpr : public Expr { -private: +protected: TreeExpr( InfixOp *infix_op, Expr *gen_expr, TreeExpr *left, TreeExpr *right ); public: From 439a4f161a78ba91e7d010d517ce5ca887bcfeb5 Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Thu, 10 May 2018 20:06:02 -0700 Subject: [PATCH 7/8] typo --- src/libprojectM/MilkdropPresetFactory/Expr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Expr.cpp b/src/libprojectM/MilkdropPresetFactory/Expr.cpp index cf58b1b95..ef8a23f12 100755 --- a/src/libprojectM/MilkdropPresetFactory/Expr.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Expr.cpp @@ -207,7 +207,7 @@ std::ostream &TreeExpr::to_string(std::ostream &out) case INFIX_MINUS: out << "-"; break; case INFIX_MULT: - out << "+"; break; + out << "*"; break; case INFIX_MOD: out << "%"; break; case INFIX_OR: From 66db7ade788879da6996fcb4edc564f2987c4361 Mon Sep 17 00:00:00 2001 From: Matthew Bellew Date: Thu, 10 May 2018 21:40:37 -0700 Subject: [PATCH 8/8] NULL check --- src/libprojectM/MilkdropPresetFactory/Parser.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libprojectM/MilkdropPresetFactory/Parser.cpp b/src/libprojectM/MilkdropPresetFactory/Parser.cpp index 3859d1ba6..47df19ce6 100755 --- a/src/libprojectM/MilkdropPresetFactory/Parser.cpp +++ b/src/libprojectM/MilkdropPresetFactory/Parser.cpp @@ -982,9 +982,11 @@ Expr * Parser::_parse_gen_expr ( std::istream & fs, TreeExpr * tree_expr, Milkd 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::cout << opt << std::endl << std::endl; return opt; }