📄 eval.c
字号:
/***************************************************************************** * eval.c: ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: eval.c 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Cyril Deguet <asmax@videolan.org> * code from projectM http://xmms-projectm.sourceforge.net * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//* Evaluation Code */#include <stdio.h>#include <stdlib.h>#include "common.h"#include "fatal.h"#include "param_types.h"#include "func_types.h"#include "expr_types.h"#include "eval.h"#include "engine_vars.h"#include "builtin_funcs.h"#define EVAL_ERROR -1/* All infix operators (except '=') are prototyped here */infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult, * infix_or, * infix_and, * infix_mod, * infix_negative, * infix_positive;int mesh_i=-1, mesh_j=-1;static inline double eval_tree_expr(tree_expr_t * tree_expr);static inline double eval_prefun_expr(prefun_expr_t * prefun_expr);static inline double eval_val_expr(val_expr_t * val_expr);inline double eval_gen_expr(gen_expr_t * gen_expr) { double l; if (gen_expr == NULL) return 0; switch(gen_expr->type) { case VAL_T: return eval_val_expr(gen_expr->item); case PREFUN_T: l = eval_prefun_expr(gen_expr->item); //if (EVAL_DEBUG) printf("eval_gen_expr: prefix function return value: %f\n", l); return l; case TREE_T: return eval_tree_expr(gen_expr->item); default: #ifdef EVAL_DEBUG printf("eval_gen_expr: general expression matched no cases!\n"); #endif return EVAL_ERROR; } }/* Evaluates functions in prefix form */static inline double eval_prefun_expr(prefun_expr_t * prefun_expr) { int i; /* This is slightly less than safe, since who knows if the passed argument is valid. For speed purposes we'll go with this */ double arg_list[prefun_expr->num_args]; #ifdef EVAL_DEBUG printf("fn["); fflush(stdout); #endif /* Evaluate each argument before calling the function itself */ for (i = 0; i < prefun_expr->num_args; i++) { arg_list[i] = eval_gen_expr(prefun_expr->expr_list[i]); #ifdef EVAL_DEBUG if (i < (prefun_expr->num_args - 1)) printf(", "); fflush(stdout); #endif } #ifdef EVAL_DEBUG printf("]"); fflush(stdout); #endif /* Now we call the function, passing a list of doubles as its argument */ return (prefun_expr->func_ptr)(arg_list); } /* Evaluates a value expression */static inline double eval_val_expr(val_expr_t * val_expr) { /* Shouldn't happen */ if (val_expr == NULL) return EVAL_ERROR; /* Value is a constant, return the double value */ if (val_expr->type == CONSTANT_TERM_T) { #ifdef EVAL_DEBUG printf("%.4f", val_expr->term.constant); fflush(stdout); #endif return (val_expr->term.constant); } /* Value is variable, dereference it */ if (val_expr->type == PARAM_TERM_T) { switch (val_expr->term.param->type) { case P_TYPE_BOOL: #ifdef EVAL_DEBUG printf("(%s:%.4f)", val_expr->term.param->name, (double)(*((int*)(val_expr->term.param->engine_val)))); fflush(stdout); #endif return (double)(*((int*)(val_expr->term.param->engine_val))); case P_TYPE_INT: #ifdef EVAL_DEBUG printf("(%s:%.4f)", val_expr->term.param->name, (double)(*((int*)(val_expr->term.param->engine_val)))); fflush(stdout); #endif return (double)(*((int*)(val_expr->term.param->engine_val))); case P_TYPE_DOUBLE: #ifdef EVAL_DEBUG printf("(%s:%.4f)", val_expr->term.param->name, (*((double*)val_expr->term.param->engine_val))); fflush(stdout); #endif if (val_expr->term.param->matrix_flag | (val_expr->term.param->flags & P_FLAG_ALWAYS_MATRIX)) { if (mesh_j >= 0) { return (((double**)val_expr->term.param->matrix)[mesh_i][mesh_j]); } else { return (((double*)val_expr->term.param->matrix)[mesh_i]); } } return *((double*)(val_expr->term.param->engine_val)); default: return ERROR; } } /* Unknown type, return failure */ return FAILURE;}/* Evaluates an expression tree */static inline double eval_tree_expr(tree_expr_t * tree_expr) { double left_arg, right_arg; infix_op_t * infix_op; /* Shouldn't happen */ if (tree_expr == NULL) return EVAL_ERROR; /* A leaf node, evaluate the general expression. If the expression is null as well, return zero */ if (tree_expr->infix_op == NULL) { if (tree_expr->gen_expr == NULL) return 0; else return eval_gen_expr(tree_expr->gen_expr); } /* Otherwise, this node is an infix operator. Evaluate accordingly */ infix_op = (infix_op_t*)tree_expr->infix_op; #ifdef EVAL_DEBUG printf("("); fflush(stdout); #endif left_arg = eval_tree_expr(tree_expr->left); #ifdef EVAL_DEBUG switch (infix_op->type) { case INFIX_ADD: printf("+"); break; case INFIX_MINUS: printf("-"); break; case INFIX_MULT: printf("*"); break; case INFIX_MOD: printf("%%"); break; case INFIX_OR: printf("|"); break; case INFIX_AND: printf("&"); break; case INFIX_DIV: printf("/"); break; default: printf("?"); } fflush(stdout); #endif right_arg = eval_tree_expr(tree_expr->right); #ifdef EVAL_DEBUG printf(")"); fflush(stdout); #endif switch (infix_op->type) { case INFIX_ADD: return (left_arg + right_arg); case INFIX_MINUS: return (left_arg - right_arg); case INFIX_MULT: return (left_arg * right_arg); case INFIX_MOD: if ((int)right_arg == 0) { #ifdef EVAL_DEBUG printf("eval_tree_expr: modulo zero!\n"); #endif return DIV_BY_ZERO; } return ((int)left_arg % (int)right_arg); case INFIX_OR: return ((int)left_arg | (int)right_arg); case INFIX_AND: return ((int)left_arg & (int)right_arg); case INFIX_DIV: if (right_arg == 0) { #ifdef EVAL_DEBUG printf("eval_tree_expr: division by zero!\n"); #endif return MAX_DOUBLE_SIZE; } return (left_arg / right_arg); default: #ifdef EVAL_DEBUG printf("eval_tree_expr: unknown infix operator!\n"); #endif return ERROR; } return ERROR;} /* Converts a double value to a general expression */gen_expr_t * const_to_expr(double val) { gen_expr_t * gen_expr; val_expr_t * val_expr; term_t term; term.constant = val; if ((val_expr = new_val_expr(CONSTANT_TERM_T, term)) == NULL) return NULL; gen_expr = new_gen_expr(VAL_T, (void*)val_expr); if (gen_expr == NULL) { free_val_expr(val_expr); } return gen_expr;}/* Converts a regular parameter to an expression */gen_expr_t * param_to_expr(param_t * param) { gen_expr_t * gen_expr = NULL; val_expr_t * val_expr = NULL; term_t term; if (param == NULL) return NULL; /* This code is still a work in progress. We need to figure out if the initial condition is used for each per frame equation or not. I am guessing that it isn't, and it is thusly implemented this way */ /* Current guess of true behavior (08/01/03) note from carm First try to use the per_pixel_expr (with cloning). If it is null however, use the engine variable instead. */ /* 08/20/03 : Presets are now objects, as well as per pixel equations. This ends up making the parser handle the case where parameters are essentially per pixel equation substitutions */ term.param = param; if ((val_expr = new_val_expr(PARAM_TERM_T, term)) == NULL) return NULL; if ((gen_expr = new_gen_expr(VAL_T, (void*)val_expr)) == NULL) { free_val_expr(val_expr); return NULL; } return gen_expr;}/* Converts a prefix function to an expression */gen_expr_t * prefun_to_expr(double (*func_ptr)(), gen_expr_t ** expr_list, int num_args) { gen_expr_t * gen_expr; prefun_expr_t * prefun_expr; /* Malloc a new prefix function expression */ prefun_expr = (prefun_expr_t*)malloc(sizeof(prefun_expr_t)); if (prefun_expr == NULL) return NULL; prefun_expr->num_args = num_args; prefun_expr->func_ptr = func_ptr; prefun_expr->expr_list = expr_list; gen_expr = new_gen_expr(PREFUN_T, (void*)prefun_expr); if (gen_expr == NULL) free_prefun_expr(prefun_expr); return gen_expr;}/* Creates a new tree expression */tree_expr_t * new_tree_expr(infix_op_t * infix_op, gen_expr_t * gen_expr, tree_expr_t * left, tree_expr_t * right) { tree_expr_t * tree_expr; tree_expr = (tree_expr_t*)malloc(sizeof(tree_expr_t)); if (tree_expr == NULL) return NULL; tree_expr->infix_op = infix_op; tree_expr->gen_expr = gen_expr; tree_expr->left = left; tree_expr->right = right; return tree_expr;}/* Creates a new value expression */val_expr_t * new_val_expr(int type, term_t term) { val_expr_t * val_expr; val_expr = (val_expr_t*)malloc(sizeof(val_expr_t)); if (val_expr == NULL) return NULL; val_expr->type = type; val_expr->term = term; return val_expr;}/* Creates a new general expression */gen_expr_t * new_gen_expr(int type, void * item) { gen_expr_t * gen_expr; gen_expr = (gen_expr_t*)malloc(sizeof(gen_expr_t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -