- SplayTree is gone! excellent.

- some issues with load_custom_wave/shape_init_conds. will resolve soon


git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/personal/carm/dev-1.0@271 6778bc44-b910-0410-a7a0-be141de4315d
This commit is contained in:
w1z7ard
2007-07-21 02:41:35 +00:00
parent 4730ed89c8
commit 86001df5ee
21 changed files with 269 additions and 907 deletions

View File

@ -15,6 +15,10 @@
/* Loads a builtin function */
#include "BuiltinFuncs.hpp"
#include <string>
#include "Algorithms.hpp"
using namespace Algorithms;
std::map<std::string, Func*> * BuiltinFuncs::builtin_func_tree = 0;
@ -40,23 +44,19 @@ int BuiltinFuncs::load_builtin_func(char * name, float (*func_ptr)(float*), int
/* Find a function given its name */
Func * BuiltinFuncs::find_func(char * name) {
Func * func = NULL;
/* First look in the builtin database */
func = (Func *)builtin_func_tree->splay_find(name);
return func;
std::map<std::string, Func*>::iterator pos = builtin_func_tree->find(std::string(name));
if (pos == builtin_func_tree->end())
return 0;
return pos->second;
}
/* Remove a function from the database */
int BuiltinFuncs::remove_func( Func *func ) {
builtin_func_tree->splay_delete(func->name);
return PROJECTM_SUCCESS;
}
int BuiltinFuncs::load_all_builtin_func() {
@ -129,7 +129,7 @@ int BuiltinFuncs::init_builtin_func_db() {
int retval;
builtin_func_tree =
std::map<std::string, Func*>::create_splaytree((int (*)(const void*,const void*))SplayKeyFunctions::compare_string, (void*(*)(void*))SplayKeyFunctions::copy_string, (void(*)(void*))SplayKeyFunctions::free_string);
new std::map<std::string, Func*>();
if (builtin_func_tree == NULL)
return PROJECTM_OUTOFMEM_ERROR;
@ -144,14 +144,15 @@ int BuiltinFuncs::init_builtin_func_db() {
Generally, do this on projectm exit */
int BuiltinFuncs::destroy_builtin_func_db() {
builtin_func_tree->splay_traverse((void (*)(void*))free_func_helper);
return PROJECTM_SUCCESS;
traverse<TraverseFunctors::DeleteFunctor<Func> >(*builtin_func_tree);
return PROJECTM_SUCCESS;
}
/* Insert a function into the database */
int BuiltinFuncs::insert_func( Func *func ) {
builtin_func_tree->splay_insert(func, func->name);
/// @bug check to see if this inserts properly
builtin_func_tree->insert(std::make_pair(std::string(func->name), func));
return PROJECTM_SUCCESS;
}

View File

@ -3,6 +3,9 @@
#include "BuiltinParams.hpp"
#include "projectM.hpp"
#include <cassert>
#include "Algorithms.hpp"
using namespace Algorithms;
BuiltinParams::BuiltinParams() {}
@ -94,8 +97,7 @@ int BuiltinParams::load_builtin_param_float(char * name, void * engine_val, void
int BuiltinParams::destroy_builtin_param_db()
{
builtin_param_tree->traverse
<SplayTreeFunctors::Delete<Param> >();
Algorithms::traverse<TraverseFunctors::DeleteFunctor<Param> >(*builtin_param_tree);
delete builtin_param_tree;
builtin_param_tree = NULL;
return PROJECTM_SUCCESS;
@ -209,8 +211,9 @@ int BuiltinParams::load_builtin_param_bool(char * name, void * engine_val, short
/* Inserts a parameter into the builtin database */
int BuiltinParams::insert_builtin_param( Param *param )
{
std::pair<std::map<std::string, Param*>::iterator, bool> inserteePos = builtin_param_tree->insert(std::make_pair(param->name, param));
return builtin_param_tree->splay_insert(param, param->name);
return inserteePos.second;
}
@ -221,7 +224,7 @@ int BuiltinParams::init_builtin_param_db(const PresetInputs & presetInputs, Pres
{
/* Create the builtin parameter splay tree (go Sleator...) */
if ((this->builtin_param_tree = std::map<std::string,Param*>::create_splaytree((int (*)(const void*,const void*))SplayKeyFunctions::compare_string,(void* (*)(void*)) SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string)) == NULL)
if ((this->builtin_param_tree = new std::map<std::string,Param*>()) == NULL)
{
if (BUILTIN_PARAMS_DEBUG) printf("init_builtin_param_db: failed to initialize database (FATAL)\n");
return PROJECTM_OUTOFMEM_ERROR;
@ -358,4 +361,4 @@ int BuiltinParams::load_all_builtin_param(const PresetInputs & presetInputs, Pre
return PROJECTM_SUCCESS;
}
}

View File

@ -67,7 +67,7 @@ public:
template <class Fun>
void traverse(Fun & fun) {
Algorithms::traverse(builtin_param_tree, fun);
Algorithms::traverse(*builtin_param_tree, fun);
}

View File

@ -37,8 +37,10 @@
#include "ParamUtils.hpp"
#include "InitCondUtils.hpp"
#include "wipemalloc.h"
#include "Algorithms.hpp"
using namespace Algorithms;
void eval_custom_shape_init_conds(CustomShape * custom_shape);
void load_unspec_init_cond_shape(Param * param);
@ -54,17 +56,17 @@ CustomShape::CustomShape( int id ) {
this->per_frame_init_eqn_string_index = 0;
/* Initialize tree data structures */
this->param_tree =
std::map<std::string,Param*>::create_splaytree( (int (*)(const void*,const void*))SplayKeyFunctions::compare_string, (void* (*)(void*)) SplayKeyFunctions::copy_string,(void (*)(void*)) SplayKeyFunctions::free_string);
this->param_tree = new
std::map<std::string,Param*>();
this->per_frame_eqn_tree =
std::map<int, PerFrameEqn*>::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_int, (void* (*)(void*))SplayKeyFunctions::copy_int,(void (*)(void*))SplayKeyFunctions::free_int);
std::map<int, PerFrameEqn*>();
this->init_cond_tree =
std::map<std::string,InitCond*>::create_splaytree((int (*)(const void*,const void*))SplayKeyFunctions::compare_string, (void* (*)(void*)) SplayKeyFunctions::copy_string,(void (*)(void*)) SplayKeyFunctions::free_string);
std::map<std::string,InitCond*>();
this->per_frame_init_eqn_tree =
std::map<std::string,InitCond*>::create_splaytree((int (*)(const void*, const void*)) SplayKeyFunctions::compare_string, (void* (*)(void*))SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string);
std::map<std::string,InitCond*>();
/* Start: Load custom shape parameters */
param = Param::new_param_float("r", P_FLAG_NONE, &this->r, NULL, 1.0, 0.0, 0.5);
@ -199,11 +201,11 @@ CustomShape::~CustomShape() {
if (param_tree == NULL)
return;
per_frame_eqn_tree->traverse<SplayTreeFunctors::Delete<PerFrameEqn> >();
init_cond_tree->traverse<SplayTreeFunctors::Delete<InitCond> >();
param_tree->traverse<SplayTreeFunctors::Delete<Param> > ();
per_frame_init_eqn_tree->traverse<SplayTreeFunctors::Delete<InitCond> > ();
traverse<TraverseFunctors::DeleteFunctor<PerFrameEqn> >(per_frame_eqn_tree);
traverse<TraverseFunctors::DeleteFunctor<InitCond> >(init_cond_tree);
traverse<TraverseFunctors::DeleteFunctor<Param> >(*param_tree);
traverse<TraverseFunctors::DeleteFunctor<InitCond> >(per_frame_init_eqn_tree);
return;
}
@ -213,13 +215,15 @@ void CustomShape::load_custom_shape_init() {
}
void CustomShape::eval_custom_shape_init_conds() {
per_frame_init_eqn_tree->splay_traverse((void (*)(void*))eval_init_cond_helper );
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end();++pos)
pos->second->evaluate();
}
void CustomShape::load_unspecified_init_conds_shape() {
InitCondUtils::LoadUnspecInitCond fun(*this->init_cond_tree, *this->per_frame_init_eqn_tree);
InitCondUtils::LoadUnspecInitCond fun(this->init_cond_tree, this->per_frame_init_eqn_tree);
param_tree->traverse(fun);
traverse(*param_tree, fun);
}

View File

@ -88,9 +88,9 @@ public:
float t8;
/* Data structure to hold per frame / per frame init equations */
std::map<std::string,InitCond*> * init_cond_tree;
std::map<int, PerFrameEqn*> * per_frame_eqn_tree;
std::map<std::string,InitCond*> * per_frame_init_eqn_tree;
std::map<std::string,InitCond*> init_cond_tree;
std::map<int, PerFrameEqn*> per_frame_eqn_tree;
std::map<std::string,InitCond*> per_frame_init_eqn_tree;
/* Denotes the index of the last character for each stdring buffer */
int per_frame_eqn_string_index;

View File

@ -77,40 +77,6 @@ CustomWave::CustomWave(int id):id(id)
this->value2 = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
this->sample_mesh = (float*)wipemalloc(MAX_SAMPLE_SIZE*sizeof(float));
/* Initialize tree data structures */
if ((this->param_tree =
std::map<std::string,Param*>::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_string, (void* (*)(void*))SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string)) == NULL) {
delete(this);
abort();
}
if ((this->per_point_eqn_tree =
std::map<int, PerPointEqn*>::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_int, (void* (*)(void*))SplayKeyFunctions::copy_int, (void (*)(void*))SplayKeyFunctions::free_int)) == NULL) {
delete(this);
abort();
}
if ((this->per_frame_eqn_tree =
std::map<int, PerFrameEqn*>::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_int,(void* (*)(void*)) SplayKeyFunctions::copy_int,(void (*)(void*)) SplayKeyFunctions::free_int)) == NULL) {
delete(this);
abort();
}
if ((this->init_cond_tree =
std::map<std::string,InitCond*>::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_string, (void*(*)(void*))SplayKeyFunctions::copy_string,(void (*)(void*)) SplayKeyFunctions::free_string)) == NULL) {
delete(this);
/// @bug make exception
abort();
}
if ((this->per_frame_init_eqn_tree =
std::map<std::string,InitCond*>::create_splaytree((int (*)(const void*, const void*))SplayKeyFunctions::compare_string, (void*(*)(void*))SplayKeyFunctions::copy_string, (void (*)(void*))SplayKeyFunctions::free_string)) == NULL) {
delete(this);
/// @bug make exception
abort();
}
/* Start: Load custom wave parameters */
@ -120,9 +86,7 @@ CustomWave::CustomWave(int id):id(id)
abort();
}
if (ParamUtils::insert(param, this->param_tree) < 0) {
delete(this);
/// @bug make exception
abort();
}
@ -431,13 +395,22 @@ CustomWave::~CustomWave() {
return;
per_point_eqn_tree->traverse<SplayTreeFunctors::Delete<PerPointEqn> >();
per_frame_eqn_tree->traverse<SplayTreeFunctors::Delete<PerFrameEqn> >();
init_cond_tree->traverse<SplayTreeFunctors::Delete<InitCond> >();
param_tree->traverse<SplayTreeFunctors::Delete<Param> > ();
per_frame_init_eqn_tree->traverse<SplayTreeFunctors::Delete<InitCond> > ();
for (std::map<int, PerPointEqn*>::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end(); ++pos)
delete(pos->second);
for (std::map<int, PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
delete(pos->second);
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
delete(pos->second);
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
delete(pos->second);
for (std::map<std::string, Param*>::iterator pos = param_tree->begin(); pos != param_tree->end(); ++pos)
delete(pos->second);
free(r_mesh);
free(g_mesh);
free(b_mesh);
@ -488,22 +461,24 @@ int CustomWave::add_per_point_eqn(char * name, GenExpr * gen_expr) {
}
/* Find most largest index in the splaytree */
if ((per_point_eqn = (PerPointEqn*)per_point_eqn_tree->splay_find_max()) == NULL)
std::map<int, PerPointEqn*>::iterator pos = --per_point_eqn_tree.end();
if (pos == per_point_eqn_tree.end())
index = 0;
else
index = per_point_eqn->index+1;
index = pos->second->index+1;
/* Create the per pixel equation given the index, parameter, and general expression */
if ((per_point_eqn = PerPointEqn::new_per_point_eqn(index, param, gen_expr)) == NULL)
if ((per_point_eqn = new PerPointEqn(index, param, gen_expr, samples)) == NULL)
return PROJECTM_FAILURE;
if (CUSTOM_WAVE_DEBUG)
printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name);
printf("add_per_point_eqn: created new equation (index = %d) (name = \"%s\")\n", per_point_eqn->index, per_point_eqn->param->name.c_str());
/* Insert the per pixel equation into the preset per pixel database */
if (per_point_eqn_tree->splay_insert(per_point_eqn, &per_point_eqn->index) < 0) {
delete per_point_eqn;
return PROJECTM_FAILURE;
}
per_point_eqn_tree.insert(std::make_pair(per_point_eqn->index, per_point_eqn));
/* Done */
return PROJECTM_SUCCESS;
@ -511,8 +486,12 @@ int CustomWave::add_per_point_eqn(char * name, GenExpr * gen_expr) {
void CustomWave::eval_custom_wave_init_conds() {
init_cond_tree->splay_traverse((void (*)(void*))eval_init_cond_helper );
per_frame_init_eqn_tree->splay_traverse((void (*)(void*))eval_init_cond_helper );
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
pos->second->evaluate();
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
pos->second->evaluate();
}
/** Evaluate per-point equations */
@ -534,8 +513,8 @@ void CustomWave::evalPerPointEqns() {
y_mesh[x] = y;
/* Evaluate per pixel equations */
abort();
per_point_eqn_tree->splay_traverse((void (*)(void*))eval_per_point_eqn_helper);
for (std::map<int, PerPointEqn*>::iterator pos = per_point_eqn_tree.begin(); pos != per_point_eqn_tree.end();++pos)
pos->second->evaluate();
/* Reset index */
projectM::currentEngine->mesh_i = -1;
@ -543,9 +522,8 @@ void CustomWave::evalPerPointEqns() {
void CustomWave::load_unspecified_init_conds() {
InitCondUtils::LoadUnspecInitCond fun(*this->init_cond_tree, *this->per_frame_init_eqn_tree);
param_tree->traverse(fun);
InitCondUtils::LoadUnspecInitCond fun(this->init_cond_tree, this->per_frame_init_eqn_tree);
Algorithms::traverse(*param_tree, fun);
}

View File

@ -110,10 +110,10 @@ public:
float v1,v2;
/* Data structures to hold per frame and per point equations */
std::map<std::string,InitCond*> * init_cond_tree;
std::map<int, PerFrameEqn*> * per_frame_eqn_tree;
std::map<int, PerPointEqn*> * per_point_eqn_tree;
std::map<std::string,InitCond*> * per_frame_init_eqn_tree;
std::map<std::string,InitCond*> init_cond_tree;
std::map<int, PerFrameEqn*> per_frame_eqn_tree;
std::map<int, PerPointEqn*> per_point_eqn_tree;
std::map<std::string,InitCond*> per_frame_init_eqn_tree;
/* Denotes the index of the last character for each string buffer */
int per_point_eqn_string_index;
@ -135,9 +135,8 @@ public:
void evalPerPointEqns();
void load_unspecified_init_conds();
void load_unspec_init_cond() ;
void eval_custom_wave_init_conds();
void load_unspec_init_cond(Param * param);
void evalPerPointEqn(PerPointEqn * per_point_eqn);

View File

@ -26,7 +26,7 @@
* $Log$
*/
/* eval.h: evaluation functions of expressions */
/* Eval.hpp: evaluation functions of expressions */
#ifndef _EVAL_H
#define _EVAL_H

View File

@ -25,18 +25,19 @@
#include "Eval.hpp"
#include <cassert>
float GenExpr::eval_gen_expr() {
float GenExpr::eval_gen_expr(int mesh_i, int mesh_j) {
float l;
switch(type) {
case VAL_T:
return ((ValExpr*)item)->eval_val_expr();
return ((ValExpr*)item)->eval_val_expr(mesh_i, mesh_j);
case PREFUN_T:
l = ((PrefunExpr *)item)->eval_prefun_expr();
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();
return ((TreeExpr*)(item))->eval_tree_expr(mesh_i, mesh_j);
default:
#ifdef EVAL_DEBUG
DWRITE( "eval_gen_expr: general expression matched no cases!\n");
@ -47,7 +48,7 @@ float GenExpr::eval_gen_expr() {
}
/* Evaluates functions in prefix form */
float PrefunExpr::eval_prefun_expr() {
float PrefunExpr::eval_prefun_expr(int mesh_i, int mesh_j) {
int i;
float rv;
@ -63,7 +64,7 @@ float PrefunExpr::eval_prefun_expr() {
#endif
/* Evaluate each argument before calling the function itself */
for (i = 0; i < num_args; i++) {
arg_list[i] = expr_list[i]->eval_gen_expr();
arg_list[i] = expr_list[i]->eval_gen_expr(mesh_i, mesh_j);
#ifdef EVAL_DEBUG_DOUBLE
if (i < (num_args - 1))
DWRITE( ", ");
@ -83,8 +84,9 @@ float PrefunExpr::eval_prefun_expr() {
return rv;
}
/* Evaluates a value expression */
float ValExpr::eval_val_expr() {
float ValExpr::eval_val_expr(int mesh_i, int mesh_j) {
/* Shouldn't happen */
/* Value is a constant, return the float value */
@ -120,7 +122,7 @@ float ValExpr::eval_val_expr() {
if (term.param->matrix_flag | (term.param->flags & P_FLAG_ALWAYS_MATRIX)) {
/** Sanity check the matrix is there... */
/* Sanity check the matrix is there... */
assert(term.param->matrix != NULL );
if (projectM::currentEngine->mesh_i >= 0) {
@ -141,7 +143,7 @@ float ValExpr::eval_val_expr() {
}
/* Evaluates an expression tree */
float TreeExpr::eval_tree_expr() {
float TreeExpr::eval_tree_expr(int mesh_i, int mesh_j) {
float left_arg, right_arg;
@ -150,7 +152,7 @@ float TreeExpr::eval_tree_expr() {
if (gen_expr == NULL)
return 0;
else
return gen_expr->eval_gen_expr();
return gen_expr->eval_gen_expr( mesh_i, mesh_j);
}
/* Otherwise, this node is an infix operator. Evaluate
@ -160,7 +162,7 @@ float TreeExpr::eval_tree_expr() {
DWRITE( "(");
#endif
left_arg = left->eval_tree_expr();
left_arg = left->eval_tree_expr(mesh_i, mesh_j);
#ifdef EVAL_DEBUG
@ -192,7 +194,7 @@ float TreeExpr::eval_tree_expr() {
#endif
right_arg = right->eval_tree_expr();
right_arg = right->eval_tree_expr(mesh_i, mesh_j);
#ifdef EVAL_DEBUG
DWRITE( ")");

View File

@ -40,77 +40,86 @@ class Param;
#define EVAL_ERROR -1
/* Infix Operator Function */
class InfixOp {
class InfixOp
{
public:
int type;
int precedence;
int type;
int precedence;
DLLEXPORT InfixOp( int type, int precedence );
};
DLLEXPORT InfixOp( int type, int precedence );
};
/** Term */
class Term {
class Term
{
public:
float constant; /* static variable */
Param *param; /* pointer to a changing variable */
float constant; /* static variable */
Param *param; /* pointer to a changing variable */
Term() { this->constant = 0; this->param = 0; }
};
Term() { this->constant = 0; this->param = 0; }
};
/* General Expression Type */
class GenExpr {
class GenExpr
{
public:
int type;
void * item;
int type;
void * item;
~GenExpr();
~GenExpr();
static GenExpr *new_gen_expr( int type, void *item );
GenExpr *clone_gen_expr();
float eval_gen_expr();
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 );
};
static GenExpr *new_gen_expr( int type, void *item );
GenExpr *clone_gen_expr();
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 );
};
/* Value expression, contains a term union */
class ValExpr {
class ValExpr
{
public:
int type;
Term term;
int type;
Term term;
~ValExpr();
static ValExpr *new_val_expr( int type, Term *term );
ValExpr *clone_val_expr();
~ValExpr();
static ValExpr *new_val_expr( int type, Term *term );
ValExpr *clone_val_expr();
float eval_val_expr();
};
float eval_val_expr(int mesh_i, int mesh_j);
};
/* A binary expression tree ordered by operator precedence */
class TreeExpr {
class TreeExpr
{
public:
InfixOp * infix_op; /* null if leaf */
GenExpr * gen_expr;
TreeExpr *left, *right;
InfixOp * infix_op; /* null if leaf */
GenExpr * gen_expr;
TreeExpr *left, *right;
~TreeExpr();
static TreeExpr *new_tree_expr( InfixOp *infix_op, GenExpr *gen_expr,
TreeExpr *left, TreeExpr *right );
TreeExpr *clone_tree_expr();
float eval_tree_expr();
};
~TreeExpr();
static TreeExpr *new_tree_expr( InfixOp *infix_op, GenExpr *gen_expr,
TreeExpr *left, TreeExpr *right );
TreeExpr *clone_tree_expr();
float eval_tree_expr(int mesh_i, int mesh_j);
};
/* A function expression in prefix form */
class PrefunExpr {
class PrefunExpr
{
public:
float (*func_ptr)(void*);
int num_args;
GenExpr **expr_list;
float (*func_ptr)(void*);
int num_args;
GenExpr **expr_list;
~PrefunExpr();
PrefunExpr *clone_prefun_expr();
float eval_prefun_expr();
};
~PrefunExpr();
PrefunExpr *clone_prefun_expr();
/* Evaluates functions in prefix form */
float eval_prefun_expr(int mesh_i, int mesh_j);
};
#endif /** _EXPR_H */

View File

@ -35,12 +35,14 @@ inline void LoadUnspecInitCond::operator() (Param * param) {
/* If initial condition was not defined by the preset file, force a default one
with the following code */
if ((init_cond = m_initCondTree.splay_find(param->name)) == NULL) {
if (m_initCondTree.find(param->name) == m_initCondTree.end()) {
/* Make sure initial condition does not exist in the set of per frame initial equations */
if ((init_cond = m_perFrameInitEqnTree.splay_find(param->name)) != NULL)
return;
if (m_perFrameInitEqnTree.find(param->name) != m_perFrameInitEqnTree.end())
return;
// Set an initial vialue via correct union member
if (param->type == P_TYPE_BOOL)
init_val.bool_val = 0;
@ -56,10 +58,9 @@ inline void LoadUnspecInitCond::operator() (Param * param) {
return;
/* Insert the initial condition into this presets tree */
if (m_initCondTree.splay_insert(init_cond, init_cond->param->name) < 0) {
delete init_cond;
return;
}
/// @bug check the reult status of insert
m_initCondTree.insert(std::make_pair(init_cond->param->name, init_cond));
}

View File

@ -41,9 +41,9 @@
#include "wipemalloc.h"
/** Constructor */
Param::Param( std::string name, short int type, short int flags, void * engine_val, void * matrix,
Param::Param( std::string _name, short int type, short int flags, void * engine_val, void * matrix,
CValue default_init_val, CValue upper_bound, CValue lower_bound):
m_name(name),
name(_name),
type(type),
flags (flags),
matrix_flag (0),
@ -61,11 +61,12 @@ Param::Param( std::string name, short int type, short int flags, void * engine_v
/* Creates a user defined parameter */
Param::Param(char * name) :
Param::Param(std::string _name) :
type(P_TYPE_DOUBLE),
flags(P_FLAG_USERDEF),
matrix_flag(0),
matrix(0)
matrix(0),
name(_name)
{
engine_val = new float();
@ -73,12 +74,7 @@ Param::Param(char * name) :
default_init_val.float_val = DEFAULT_DOUBLE_IV;
upper_bound.float_val = DEFAULT_DOUBLE_UB;
lower_bound.float_val = DEFAULT_DOUBLE_LB;
/* Copy given name into parameter structure */
strncpy(this->name, name, MAX_TOKEN_SIZE-1);
(*(float*)this->engine_val) = DEFAULT_DOUBLE_IV;
/** @@FIX THIS */
//this->gx = projectM::currentEngine->gx;
@ -107,7 +103,7 @@ Param::~Param() {
}
}
if (PARAM_DEBUG) printf("free_param: freeing \"%s\".\n", name);
if (PARAM_DEBUG) printf("free_param: freeing \"%s\".\n", name.c_str());
}
/* Compare string name with parameter name */

View File

@ -72,7 +72,7 @@ public:
int gx, gy;
/* Function prototypes */
Param(char *name, short int type, short int flags,
Param(std::string name, short int type, short int flags,
void * eqn_val, void *matrix,
CValue default_init_val, CValue upper_bound,
CValue lower_bound);
@ -84,9 +84,6 @@ public:
static int init_user_param_db();
static int destroy_user_param_db();
int remove_param();
//int insert_param( SplayTree *database );
void load_unspec_init_cond();
void load_unspec_init_cond_shape();

View File

@ -15,15 +15,14 @@ class BuiltinParams;
class ParamUtils
{
public:
static void insert(Param * param, std::map<std::string,Param*> * paramTree)
static bool insert(Param * param, std::map<std::string,Param*> * paramTree)
{
assert(param);
assert(paramTree);
paramTree->insert(std::make_pair(param->name,param))
;
return ((paramTree->insert(std::make_pair(param->name,param))).second);
}

View File

@ -1337,7 +1337,7 @@ InitCond * Parser::parse_per_frame_init_eqn(FILE * fs, Preset * preset, std::map
}
/* Compute initial condition value */
val = gen_expr->eval_gen_expr();
val = gen_expr->eval_gen_expr(-1,-1);
/* Free the general expression now that we are done with it */
delete gen_expr;
@ -1390,7 +1390,7 @@ int Parser::parse_wavecode(char * token, FILE * fs, Preset * preset) {
/* token should be in the form wavecode_N_var, such as wavecode_1_samples */
/* Get id and variable name from token string */
if (parse_wavecode_prefix(token, &id, &var_string) < 0)
if (parse_wavecode_prefix(token, &id, &var_string) < 0)
return PROJECTM_PARSE_ERROR;
//if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
@ -1437,7 +1437,7 @@ int Parser::parse_wavecode(char * token, FILE * fs, Preset * preset) {
return PROJECTM_FAILURE;
}
custom_wave->init_cond_tree->insert(std::make_pair(param->name, init_cond));
custom_wave->init_cond_tree.insert(std::make_pair(param->name, init_cond));
line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
@ -1518,7 +1518,7 @@ int Parser::parse_shapecode(char * token, FILE * fs, Preset * preset) {
return PROJECTM_FAILURE;
}
custom_shape->init_cond_tree->insert(std::make_pair(param->name,init_cond));
custom_shape->init_cond_tree.insert(std::make_pair(param->name,init_cond));
line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
//if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
@ -1747,7 +1747,7 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty
}
/* Insert the equation in the per frame equation tree */
custom_wave->per_frame_init_eqn_tree->insert(std::make_pair(init_cond->param->name,init_cond));
custom_wave->per_frame_init_eqn_tree.insert(std::make_pair(init_cond->param->name,init_cond));
if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
&custom_wave->per_frame_init_eqn_string_index) < 0) {
@ -1804,7 +1804,7 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty
return PROJECTM_FAILURE;
}
custom_wave->per_frame_eqn_tree->insert(std::make_pair(per_frame_eqn->index, per_frame_eqn));
custom_wave->per_frame_eqn_tree.insert(std::make_pair(per_frame_eqn->index, per_frame_eqn));
//if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n",
// per_frame_eqn->index, custom_wave->id);
@ -1837,14 +1837,14 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty
}
}
/* Parse right side of equation as an expression */
/* Parse right side of equation as an expression, First tell parser we are parsing a custom wave */
current_wave = custom_wave;
if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
if (PARSE_DEBUG) printf("parse_wave_helper (per_point): equation evaluated to null? (LINE %d)\n", line_count);
return PROJECTM_PARSE_ERROR;
}
current_wave = NULL;
/* Add the per point equation */
if (custom_wave->add_per_point_eqn(string, gen_expr) < 0) {
@ -1852,7 +1852,8 @@ int Parser::parse_wave_helper(FILE * fs, Preset * preset, int id, char * eqn_ty
return PROJECTM_PARSE_ERROR;
}
// This tells the parser we are no longer parsing a custom wave
current_wave = NULL;
if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
return PROJECTM_FAILURE;
@ -2009,7 +2010,7 @@ int Parser::parse_shape_per_frame_init_eqn(FILE * fs, CustomShape * custom_shape
}
/* Insert the equation in the per frame equation tree */
custom_shape->per_frame_init_eqn_tree->insert(std::make_pair(init_cond->param->name,init_cond));
custom_shape->per_frame_init_eqn_tree.insert(std::make_pair(init_cond->param->name,init_cond));
if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
&custom_shape->per_frame_init_eqn_string_index) < 0)
return PROJECTM_FAILURE;
@ -2066,7 +2067,7 @@ char string[MAX_TOKEN_SIZE];
return PROJECTM_FAILURE;
}
custom_shape->per_frame_eqn_tree->insert(std::make_pair(per_frame_eqn->index, per_frame_eqn));
custom_shape->per_frame_eqn_tree.insert(std::make_pair(per_frame_eqn->index, per_frame_eqn));
/* Need to add stuff to string buffer so the editor can read the equations.
Why not make a nice little helper function for this? - here it is: */
@ -2126,7 +2127,7 @@ char string[MAX_TOKEN_SIZE];
return PROJECTM_FAILURE;
}
custom_wave->per_frame_eqn_tree->insert(std::make_pair(per_frame_eqn->index, per_frame_eqn));
custom_wave->per_frame_eqn_tree.insert(std::make_pair(per_frame_eqn->index, per_frame_eqn));
//if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n",
// per_frame_eqn->index, custom_shape->id);

View File

@ -38,12 +38,13 @@
void PerFrameEqn::evaluate() {
if (PER_FRAME_EQN_DEBUG) {
printf("per_frame_%d=%s= ", index, param->name);
printf("per_frame_%d=%s= ", index, param->name.c_str());
fflush(stdout);
}
//*((float*)per_frame_eqn->param->engine_val) = eval_gen_expr(per_frame_eqn->gen_expr);
param->set_param(gen_expr->eval_gen_expr());
param->set_param(gen_expr->eval_gen_expr(-1,-1));
if (PER_FRAME_EQN_DEBUG) printf(" = %.4f\n", *((float*)param->engine_val));
}

View File

@ -35,7 +35,7 @@
#include <map>
#include "wipemalloc.h"
#include <cassert>
/* Evaluates a per pixel equation */
void PerPixelEqn::evaluate() {
@ -46,8 +46,8 @@ void PerPixelEqn::evaluate() {
eqn_ptr = gen_expr;
if (param->matrix == NULL) {
if (PER_PIXEL_EQN_DEBUG) printf("evalPerPixelEqn: [begin initializing matrix] (index = %d) (name = %s)\n",
index, param->name);
index, param->name.c_str());
param_matrix = (float**)wipemalloc(param->gx*sizeof(float*));
param->matrix = param_matrix;
@ -58,10 +58,6 @@ void PerPixelEqn::evaluate() {
for (y = 0; y < param->gy; y++)
param_matrix[x][y] = 0.0;
if (param->name == NULL)
printf("null parameter?\n");
// printf("PARAM MATRIX: \"%s\" initialized.\n", per_pixel_eqn->param->name);
}
else
param_matrix = (float**)param->matrix;
@ -70,23 +66,23 @@ void PerPixelEqn::evaluate() {
printf("something is seriously wrong...\n");
// param->matrix_flag = 0; /** Force matrix ignore to update time */
for (projectM::currentEngine->mesh_i = 0; projectM::currentEngine->mesh_i < param->gx; projectM::currentEngine->mesh_i++) {
for (projectM::currentEngine->mesh_j = 0; projectM::currentEngine->mesh_j < param->gy; projectM::currentEngine->mesh_j++) {
param_matrix[projectM::currentEngine->mesh_i][projectM::currentEngine->mesh_j] = eqn_ptr->eval_gen_expr();
for (int mesh_i = 0; mesh_i < param->gx; mesh_i++) {
for (int mesh_j = 0; mesh_j < param->gy; mesh_j++) {
param_matrix[mesh_i][mesh_j] = eqn_ptr->eval_gen_expr(mesh_i, mesh_j);
}
}
/* Now that this parameter has been referenced with a per
pixel equation, we let the evaluator know by setting
this flag */
param->matrix_flag = 1;
param->matrix_flag = true;
param->flags |= P_FLAG_PER_PIXEL;
}
PerPixelEqn(int _index, Param * _param, GenExrp *_gen_expr):index(_index), param(_param), gen_expr(_gen_expr) {
PerPixelEqn::PerPixelEqn(int _index, Param * _param, GenExpr * _gen_expr):index(_index), param(_param), gen_expr(_gen_expr) {
assert(index >= 0);
assert(param != NULL);
assert(gen_expr != null);
assert(param != 0);
assert(gen_expr != 0);
}

View File

@ -39,47 +39,46 @@
#include "wipemalloc.h"
/* Evaluates a per point equation for the current custom wave given by interface_wave ptr */
void PerPointEqn::evalPerPointEqn() {
void PerPointEqn::evaluate() {
int samples, size;
int size;
float * param_matrix;
GenExpr * eqn_ptr;
abort();
// samples = CustomWave::interface_wave->samples;
eqn_ptr = gen_expr;
if (param->matrix == NULL) {
if ((param_matrix = (float*) (param->matrix = wipemalloc(size = samples*sizeof(float)))) == NULL)
return;
memset(param_matrix, 0, size);
}
else
param_matrix = (float*)param->matrix;
for (projectM::currentEngine->mesh_i = 0; projectM::currentEngine->mesh_i < samples; projectM::currentEngine->mesh_i++) {
param_matrix[projectM::currentEngine->mesh_i] = eqn_ptr->eval_gen_expr();
for (int i = 0; i < samples; i++) {
// -1 is because per points only use one dimension
param_matrix[i] = eqn_ptr->eval_gen_expr(i, -1);
}
/* Now that this parameter has been referenced with a per
point equation, we let the evaluator know by setting
this flag */
param->matrix_flag = 1;
if (!param->matrix_flag)
param->matrix_flag = true;
}
PerPointEqn * PerPointEqn::new_per_point_eqn(int index, Param * param, GenExpr * gen_expr) {
PerPointEqn * per_point_eqn = NULL;
if (param == NULL)
return NULL;
if (gen_expr == NULL)
return NULL;
if ((per_point_eqn = (PerPointEqn*)wipemalloc(sizeof(PerPointEqn))) == NULL)
return NULL;
per_point_eqn->index = index;
per_point_eqn->gen_expr = gen_expr;
per_point_eqn->param = param;
return per_point_eqn;
}
PerPointEqn::PerPointEqn(int _index, Param * _param, GenExpr * _gen_expr, int _samples):
index(_index),
param(_param),
gen_expr(_gen_expr),
samples(_samples)
{}
PerPointEqn::~PerPointEqn() {

View File

@ -37,12 +37,13 @@ class PerPointEqn;
class PerPointEqn {
public:
int index;
int samples; // the number of samples to iterate over
Param *param;
GenExpr * gen_expr;
~PerPointEqn();
void evalPerPointEqn();
static PerPointEqn *new_per_point_eqn( int index, Param *param, GenExpr *gen_expr);
void evaluate();
PerPointEqn( int index, Param *param, GenExpr *gen_expr, int samples);
};

View File

@ -70,7 +70,7 @@ Preset::~Preset()
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<PerFrameEqn> >(*per_frame_eqn_tree);
delete per_frame_eqn_tree;
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<Param> >(user_param_tree);
Algorithms::traverse<Algorithms::TraverseFunctors::DeleteFunctor<Param> >(*user_param_tree);
delete user_param_tree;
/// @note no need to clear the actual container itself
@ -204,11 +204,11 @@ void Preset::evalCustomWavePerFrameEquations()
for (PresetOutputs::cwave_container::iterator pos = customWaves->begin(); pos != customWaves->end(); ++pos)
{
std::map<std::string, InitCond*> & init_cond_tree = *(*pos)->init_cond_tree;
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
_pos->second->evaluate();
std::map<int, PerFrameEqn*> & per_frame_eqn_tree = *(*pos)->per_frame_eqn_tree;
std::map<int, PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
for (std::map<int, PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
_pos->second->evaluate();
}
@ -221,11 +221,11 @@ void Preset::evalCustomShapePerFrameEquations()
for (PresetOutputs::cshape_container::iterator pos = customShapes->begin(); pos != customShapes->end(); ++pos)
{
std::map<std::string, InitCond*> & init_cond_tree = *(*pos)->init_cond_tree;
std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
_pos->second->evaluate();
std::map<int, PerFrameEqn*> & per_frame_eqn_tree = *(*pos)->per_frame_eqn_tree;
std::map<int, PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
for (std::map<int, PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
_pos->second->evaluate();
}
@ -234,21 +234,21 @@ void Preset::evalCustomShapePerFrameEquations()
void Preset::evalInitConditions()
{
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree->begin(); pos != per_frame_init_eqn_tree->end(); ++pos)
pos->second->evaluate();
for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree->begin(); pos != per_frame_init_eqn_tree->end(); ++pos)
pos->second->evaluate();
}
void Preset::evalPerFrameEquations()
{
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree->begin(); pos != init_cond_tree->end(); ++pos)
pos->second->evaluate();
for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree->begin(); pos != init_cond_tree->end(); ++pos)
pos->second->evaluate();
for (std::map<int, PerFrameEqn*>::iterator pos = per_frame_eqn_tree->begin(); pos != per_frame_eqn_tree->end(); ++pos)
pos->second->evaluate();
for (std::map<int, PerFrameEqn*>::iterator pos = per_frame_eqn_tree->begin(); pos != per_frame_eqn_tree->end(); ++pos)
pos->second->evaluate();
}
@ -261,7 +261,7 @@ void Preset::initialize(const std::string & pathname)
this->per_frame_eqn_tree = new std::map<int, PerFrameEqn*>();
this->per_pixel_eqn_tree = new std::map<int, PerPixelEqn*>();
this->per_frame_init_eqn_tree = new std::map<std::string,InitCond*>();
memset(this->per_pixel_flag, 0, sizeof(int)*NUM_OPS);
/* Set initial index values */
@ -474,17 +474,17 @@ int Preset::write_per_pixel_equations(FILE * fs)
void Preset::load_custom_wave_init_conditions()
{
for (PresetOutputs::cwave_container::iterator pos = customWaves->begin(); pos != customWaves->end(); ++pos)
(*pos)->load_unspec_init_cond();
(*pos)->load_unspec_init_cond();
}
void Preset::load_custom_shape_init_conditions()
{
// void eval_custom_shape_init_conds();
// void eval_custom_shape_init_conds();
for (PresetOutputs::cshape_container::iterator pos = customShapes->begin(); pos != customShapes->end(); ++pos)
(*pos)->load_unspec_init_cond_shape();
(*pos)->load_unspec_init_cond_shape();
}
@ -510,7 +510,9 @@ void Preset::evalPerPixelEqns()
{
/* Evaluate all per pixel equations using splay traversal */
per_pixel_eqn_tree->splay_traverse((void (*)(void*))eval_per_pixel_eqn_helper);
for (std::map<int, PerPixelEqn*>::iterator pos = per_pixel_eqn_tree->begin();
pos != per_pixel_eqn_tree->end(); ++pos)
pos->second->evaluate();
/* Set mesh i / j values to -1 so engine vars are used by default again */
this->mesh_i = -1;
@ -544,12 +546,13 @@ InitCond * Preset::get_init_cond( Param *param )
InitCond * init_cond;
CValue init_val;
if ( param == NULL )
{
return NULL;
}
assert(param);
if ((init_cond = (InitCond*)(init_cond_tree->splay_find(param->name))) == NULL)
std::map<std::string, InitCond*>::iterator pos = init_cond_tree->find(param->name);
init_cond = pos == init_cond_tree->end() ? 0 : pos->second;
if (init_cond == NULL)
{
if (param->type == P_TYPE_BOOL)
@ -566,7 +569,10 @@ InitCond * Preset::get_init_cond( Param *param )
return NULL;
/* Insert the initial condition into this presets tree */
if (init_cond_tree->splay_insert(init_cond, init_cond->param->name) < 0)
std::pair<std::map<std::string, InitCond*>::iterator, bool> inserteePair =
init_cond_tree->insert(std::make_pair(init_cond->param->name, init_cond));
if (!inserteePair.second)
{
delete init_cond;
return NULL;
@ -749,7 +755,12 @@ Param * Preset::find(char * name, int flags)
/* If the search failed, check the user database */
if (param == NULL)
{
param = (Param*)this->user_param_tree->splay_find(name);
std::map<std::string, Param*>::iterator pos = user_param_tree->find(name);
if (pos == user_param_tree->end())
param = 0;
else
param = pos->second;
}
/* If it doesn't exist in the user (or builtin) database and
@ -772,9 +783,12 @@ Param * Preset::find(char * name, int flags)
return NULL;
}
/* Finally, insert the new parameter into this preset's proper splaytree */
if (this->user_param_tree->splay_insert(param, param->name) < 0)
std::pair<std::map<std::string, Param*>::iterator, bool> inserteePair
= user_param_tree->insert(std::make_pair(param->name, param));
if (!inserteePair.second)
{
if (PARAM_DEBUG) printf("PARAM \"%s\" already exists in user parameter tree!\n", param->name);
if (PARAM_DEBUG) printf("PARAM \"%s\" already exists in user parameter tree!\n", param->name.c_str());
delete param;
return NULL;
}

View File

@ -1,639 +0,0 @@
/**
* projectM -- Milkdrop-esque visualisation SDK
* Copyright (C)2003-2007 projectM Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* See 'LICENSE.txt' included within this release
*
*/
/**
* $Id$
*
* Splay tree
*
* $Log$
*/
#ifndef _SPLAYTREE_HPP
#define _SPLAYTREE_HPP
#define PERFECT_MATCH 0
#define CLOSEST_MATCH 1
#include "SplayNode.hpp"
#include "compare.h"
#include "fatal.h"
#define SPLAYTEE_DUMP_FILE "./splay-dump"
template <class Data>
class SplayTree {
public:
static const int SPLAYTREE_FAILURE = PROJECTM_FAILURE;
static const int SPLAYTREE_SUCCESS = PROJECTM_SUCCESS;
SplayNode<Data> *root;
int (*compare)(const void*,const void*);
void * (*copy_key)(void *);
void (*free_key)(void*);
static SplayTree<Data> *create_splaytree(int (*compare)(const void*,const void*), void * (*copy_key)(void*), void (*free_key)(void*));
~SplayTree();
Data * splay_find(const void * key);
int splay_insert(Data * data, void * key);
int splay_insert_node( SplayNode<Data> *node );
int splay_insert_link(void * alias_key, void * orig_key);
int splay_delete(void * key);
SplayNode<Data> *splay_delete_helper( void *key, SplayNode<Data> *node,
int (*compare)(const void *,const void*),
void (*free_key)(void*) );
int splay_size();
int splay_rec_size( SplayNode<Data> *node );
SplayNode<Data> *splay( const void *key, SplayNode<Data> *t, int *match_type, int (*compare)(const void *,const void *) );
/** Traverses the entire splaytree in order given a function pointer
* @deprecated Use the traverse method instead
*/
void splay_traverse(void (*func_ptr)(void*));
SplayNode<Data> *get_splaynode_of(void * key);
void *splay_find_above_min(void * key);
void splay_find_above_min_helper( void *max_key, void **closest_key,
SplayNode<Data> *root, int (*compare)(void *,void *));
void *splay_find_below_max(void * key);
void splay_find_below_max_helper( void *min_key, void **closest_key,
SplayNode<Data> *root, int (*compare)(void *,void *));
Data *splay_find_min();
Data *splay_find_max();
/** Traverses the splay tree at each node in order with the passed in functor */
template <class Fun>
void traverse(Fun & functor);
/** Traverses the splay tree at each node in order by constructing a functor on the fly
* and using it to traverse the entire tree. This is a convenience function for functors that don't return
* any useful state to the caller. Note that the functor is assumed to take one template type which
* matches the datatype of the splay tree. See implementation for more details.
*/
template <class Fun>
void traverse();
private:
void splay_traverse_helper (void (*func_ptr)(void*), SplayNode<Data> * splaynode);
template <class Fun>
void traverseRec(Fun & fun, SplayNode<Data> * splaynode);
};
/* Creates a splay tree given a compare key function, copy key function, and free key function.
Ah yes, the wonders of procedural programming */
template <class Data>
SplayTree<Data> * SplayTree<Data>::create_splaytree(int (*compare)(const void *,const void*), void * (*copy_key)(void *), void (*free_key)(void*)) {
SplayTree * splaytree;
/* Allocate memory for the splaytree struct */
if ((splaytree = (SplayTree*)malloc(sizeof(SplayTree))) == NULL)
return NULL;
/* Set struct entries */
splaytree->root = NULL;
splaytree->compare = compare;
splaytree->copy_key = copy_key;
splaytree->free_key = free_key;
/* Return instantiated splay tree */
return splaytree;
}
/* Destroys a splay tree */
template <class Data>
SplayTree<Data>::~SplayTree() {
/* Recursively free all splaynodes in tree */
if ( root != NULL ) {
delete root;
}
}
template <class Data>
template <class Fun>
void SplayTree<Data>::traverse(Fun & functor) {
/* Call recursive helper function */
traverseRec(functor, root);
return;
}
template <class Data>
template <class Fun>
void SplayTree<Data>::traverse() {
Fun functor;
/* Call recursive helper function */
traverseRec(functor, root);
return;
}
/* Traverses the entire splay tree with the given function func_ptr */
template <class Data>
void SplayTree<Data>::splay_traverse(void (*func_ptr)(void*)) {
/* Null argument check */
if (func_ptr == NULL)
return;
/* Call recursive helper function */
splay_traverse_helper(func_ptr, root );
return;
}
/* Helper function to traverse the entire splaytree */
template <class Data>
void SplayTree<Data>::splay_traverse_helper (void (*func_ptr)(void *), SplayNode<Data> * splaynode) {
/* Normal if this happens, its a base case of recursion */
if (splaynode == NULL)
return;
/* Recursively traverse to the left */
splay_traverse_helper(func_ptr, splaynode->left);
func_ptr(splaynode->data);
/* Recursively traverse to the right */
splay_traverse_helper(func_ptr, splaynode->right);
/* Done */
return;
}
/* Helper function to traverse the entire splaytree */
template <class Data>
template <class Fun>
void SplayTree<Data>::traverseRec (Fun & fun, SplayNode<Data> * splaynode) {
/* Normal if this happens, its a base case of recursion */
if (splaynode == NULL)
return;
/* Recursively traverse to the left */
traverseRec(fun, splaynode->left);
fun(splaynode->data);
/* Recursively traverse to the right */
traverseRec(fun, splaynode->right);
/* Done */
return;
}
/* Find the node corresponding to the given key in splaytree, return its data pointer */
template <class Data>
Data * SplayTree<Data>::splay_find(const void * key) {
SplayNode<Data> * splaynode;
int match_type;
if (key == NULL)
return NULL;
splaynode = root;
/* Bring the targeted splay node to the top of the splaytree */
splaynode = splay(key, splaynode, &match_type, compare);
root = splaynode;
/* We only want perfect matches, so return null when match isn't perfect */
if (match_type == CLOSEST_MATCH)
return NULL;
/* This shouldn't happen because of the match type check, but whatever */
if (root == NULL)
return NULL;
return root->data;
}
/* Gets the splaynode that the given key points to */
template <class Data>
SplayNode<Data> * SplayTree<Data>::get_splaynode_of(void * key) {
SplayNode<Data> * splaynode;
int match_type;
/* Null argument checks */
if (key == NULL)
return NULL;
splaynode = root;
/* Find the splaynode */
splaynode = splay(key, splaynode, &match_type, compare);
root = splaynode;
/* Only perfect matches are valid */
if (match_type == CLOSEST_MATCH)
return NULL;
/* Return the perfect match splay node */
return splaynode;
}
/* Finds the desired node, and changes the tree such that it is the root */
template <class Data>
SplayNode<Data> * SplayTree<Data>::splay (const void * key, SplayNode<Data> * t, int * match_type, int (*compare)(const void*,const void*)) {
/* Simple top down splay, not requiring key to be in the tree t.
What it does is described above. */
SplayNode<Data> N, *l, *r, *y;
*match_type = CLOSEST_MATCH;
if (t == NULL) return t;
N.left = N.right = NULL;
l = r = &N;
for (;;) {
if (compare(key, t->key) < 0) {
if (t->left == NULL) break;
if (compare(key, t->left->key) < 0) {
y = t->left; /* rotate right */
t->left = y->right;
y->right = t;
t = y;
if (t->left == NULL) break;
}
r->left = t; /* link right */
r = t;
t = t->left;
} else if (compare(key, t->key) > 0) {
if (t->right == NULL) break;
if (compare(key, t->right->key) > 0) {
y = t->right; /* rotate left */
t->right = y->left;
y->left = t;
t = y;
if (t->right == NULL) break;
}
l->right = t; /* link left */
l = t;
t = t->right;
} else {
*match_type = PERFECT_MATCH;
break;
}
}
l->right = t->left; /* assemble */
r->left = t->right;
t->left = N.right;
t->right = N.left;
return t;
//return NULL;
}
/* Deletes a splay node from a splay tree. If the node doesn't exist
then nothing happens */
template <class Data>
int SplayTree<Data>::splay_delete(void * key) {
SplayNode<Data> * splaynode;
/* Use helper function to delete the node and return the resulting tree */
if ((splaynode = splay_delete_helper(key, root, compare, free_key)) == NULL)
return SPLAYTREE_FAILURE;
/* Set new splaytree root equal to the returned splaynode after deletion */
root = splaynode;
/* Finished, no errors */
return SPLAYTREE_SUCCESS;
}
/* Deletes a splay node */
template <class Data>
SplayNode<Data> * SplayTree<Data>::splay_delete_helper(void * key, SplayNode<Data> * splaynode,
int (*compare)(const void*,const void*), void (*free_key)(void*)) {
SplayNode<Data> * new_root;
int match_type;
/* Argument check */
if (splaynode == NULL)
return NULL;
splaynode = splay(key, splaynode, &match_type, compare);
/* If entry wasn't found, quit here */
if (match_type == CLOSEST_MATCH)
return NULL;
/* If the targeted node's left pointer is null, then set the new root
equal to the splaynode's right child */
if (splaynode->left == NULL) {
new_root = splaynode->right;
}
/* Otherwise, do something I don't currently understand */
else {
new_root = splay(key, splaynode->left, &match_type, compare);
new_root->right = splaynode->right;
}
/* Set splay nodes children pointers to null */
splaynode->left = splaynode->right = NULL;
/* Free the splaynode (and only this node since its children are now empty */
delete splaynode;
/* Return the resulting tree */
return new_root;
}
/* Inserts 'data' into the 'splaytree' paired with the passed 'key' */
template <class Data>
int SplayTree<Data>::splay_insert(Data * data, void * key) {
SplayNode<Data> * splaynode;
void * key_clone;
/* Null argument checks */
if (key == NULL) {
printf ("splay_insert: null key as argument, returning failure\n");
return SPLAYTREE_FAILURE;
}
/* Clone the key argument */
key_clone = copy_key(key);
/* Create a new splaynode (of regular type) */
if ((splaynode = new SplayNode<Data>(key_clone, data, free_key)) == NULL) {
free_key(key_clone);
printf ("splay_insert: out of memory?\n");
return PROJECTM_OUTOFMEM_ERROR;
}
/* Inserts the splaynode into the splaytree */
if (splay_insert_node(splaynode) < 0) {
printf ("splay_insert: failed to insert node.\n");
splaynode->left=splaynode->right=NULL;
delete splaynode;
return SPLAYTREE_FAILURE;
}
return SPLAYTREE_SUCCESS;
}
/* Helper function to insert splaynodes into the splaytree */
template <class Data>
int SplayTree<Data>::splay_insert_node(SplayNode<Data> * splaynode) {
int match_type;
int cmpval;
void * key;
SplayNode<Data> * t;
/* Null argument checks */
if (splaynode == NULL)
return SPLAYTREE_FAILURE;
key = splaynode->key;
t = root;
/* Root is null, insert splaynode here */
if (t == NULL) {
splaynode->left = splaynode->right = NULL;
root = splaynode;
return SPLAYTREE_SUCCESS;
}
t = splay(key, t, &match_type, compare);
if ((cmpval = compare(key,t->key)) < 0) {
splaynode->left = t->left;
splaynode->right = t;
t->left = NULL;
root = splaynode;
return SPLAYTREE_SUCCESS;
}
else if (cmpval > 0) {
splaynode->right = t->right;
splaynode->left = t;
t->right = NULL;
root = splaynode;
return SPLAYTREE_SUCCESS;
}
/* Item already exists in tree, don't reinsert */
else {
printf("splay_insert_node: duplicate key detected, ignoring...\n");
return SPLAYTREE_FAILURE;
}
}
/* Returns the 'maximum' key that is less than the given key in the splaytree */
template <class Data>
void * SplayTree<Data>::splay_find_below_max(void * key) {
void * closest_key;
if (root == NULL)
return NULL;
if (key == NULL)
return NULL;
closest_key = NULL;
splay_find_below_max_helper(key, &closest_key, root, compare);
if (closest_key == NULL) return NULL;
return splay_find(closest_key);
}
/* Returns the 'minimum' key that is greater than the given key in the splaytree */
template <class Data>
void * SplayTree<Data>::splay_find_above_min(void * key) {
void * closest_key;
if (root == NULL)
return NULL;
if (key == NULL)
return NULL;
closest_key = NULL;
splay_find_above_min_helper(key, &closest_key, root, compare);
if (closest_key == NULL) {
return NULL;
}
return splay_find(closest_key);
}
/* Helper function */
template <class Data>
void SplayTree<Data>::splay_find_below_max_helper(void * min_key, void ** closest_key, SplayNode<Data> * root, int (*compare)(void*,void*)) {
/* Empty root, return*/
if (root == NULL)
return;
/* The root key is less than the previously found closest key.
Also try to make the key non null if the value is less than the max key */
if ((*closest_key == NULL) || (compare(root->key, *closest_key) < 0)) {
/* The root key is less than the given max key, so this is the
smallest change from the given max key */
if (compare(root->key, min_key) > 0) {
*closest_key = root->key;
/* Look right again in case even a greater key exists that is
still less than the given max key */
splay_find_below_max_helper(min_key, closest_key, root->left, compare);
}
/* The root key is greater than the given max key, and greater than
the closest key, so search left */
else {
splay_find_below_max_helper(min_key, closest_key, root->right, compare);
}
}
/* The root key is less than the found closest key, search right */
else {
splay_find_below_max_helper(min_key, closest_key, root->left, compare);
}
}
/* Helper function */
template <class Data>
void SplayTree<Data>::splay_find_above_min_helper(void * max_key, void ** closest_key, SplayNode<Data> * root, int (*compare)(void *,void*)) {
/* Empty root, stop */
if (root == NULL)
return;
/* The root key is greater than the previously found closest key.
Also try to make the key non null if the value is less than the min key */
if ((*closest_key == NULL) || (compare(root->key, *closest_key) > 0)) {
/* The root key is greater than the given min key, so this is the
smallest change from the given min key */
if (compare(root->key, max_key) < 0) {
*closest_key = root->key;
/* Look left again in case even a smaller key exists that is
still greater than the given min key */
splay_find_above_min_helper(max_key, closest_key, root->right, compare);
}
/* The root key is less than the given min key, and less than
the closest key, so search right */
else {
splay_find_above_min_helper(max_key, closest_key, root->left, compare);
}
}
/* The root key is greater than the found closest key, search left */
else {
splay_find_above_min_helper(max_key, closest_key, root->right, compare);
}
}
/* Find the minimum entry of the splay tree */
template <class Data>
Data * SplayTree<Data>::splay_find_min() {
SplayNode<Data> * splaynode;
if (root == NULL)
return NULL;
splaynode = root;
while (splaynode->left != NULL)
splaynode= splaynode->left;
return splaynode->data;
}
/* Find the maximum entry of the splay tree */
template <class Data>
Data * SplayTree<Data>::splay_find_max() {
SplayNode<Data> * splaynode;
if (root == NULL)
return NULL;
splaynode = root;
while (splaynode->right != NULL) {
printf("data:%d\n", *(int*)splaynode->key);
splaynode = splaynode->right;
}
return splaynode->data;
}
template <class Data>
int SplayTree<Data>::splay_size() {
if ( root == NULL ) {
return SPLAYTREE_FAILURE;
}
return splay_rec_size(root);
}
template <class Data>
int SplayTree<Data>::splay_rec_size(SplayNode<Data> * splaynode) {
if (!splaynode)
return 0;
return 1 + splay_rec_size(splaynode->left) + splay_rec_size(splaynode->right);
}
#endif /** !_SPLAYTREE_HPP */