00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include "avcodec.h"
00030 #include "mpegvideo.h"
00031
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <math.h>
00036
00037 #ifndef NAN
00038 #define NAN 0
00039 #endif
00040
00041 #ifndef M_PI
00042 #define M_PI 3.14159265358979323846
00043 #endif
00044
00045 typedef struct Parser{
00046 int stack_index;
00047 char *s;
00048 double *const_value;
00049 const char **const_name;
00050 double (**func1)(void *, double a);
00051 const char **func1_name;
00052 double (**func2)(void *, double a, double b);
00053 char **func2_name;
00054 void *opaque;
00055 } Parser;
00056
00057 static double evalExpression(Parser *p);
00058
00059 static int strmatch(const char *s, const char *prefix){
00060 int i;
00061 for(i=0; prefix[i]; i++){
00062 if(prefix[i] != s[i]) return 0;
00063 }
00064 return 1;
00065 }
00066
00067 static double evalPrimary(Parser *p){
00068 double d, d2=NAN;
00069 char *next= p->s;
00070 int i;
00071
00072
00073 d= strtod(p->s, &next);
00074 if(next != p->s){
00075 p->s= next;
00076 return d;
00077 }
00078
00079
00080 for(i=0; p->const_name && p->const_name[i]; i++){
00081 if(strmatch(p->s, p->const_name[i])){
00082 p->s+= strlen(p->const_name[i]);
00083 return p->const_value[i];
00084 }
00085 }
00086
00087 p->s= strchr(p->s, '(');
00088 if(p->s==NULL){
00089 av_log(NULL, AV_LOG_ERROR, "Parser: missing ( in \"%s\"\n", next);
00090 return NAN;
00091 }
00092 p->s++;
00093 d= evalExpression(p);
00094 if(p->s[0]== ','){
00095 p->s++;
00096 d2= evalExpression(p);
00097 }
00098 if(p->s[0] != ')'){
00099 av_log(NULL, AV_LOG_ERROR, "Parser: missing ) in \"%s\"\n", next);
00100 return NAN;
00101 }
00102 p->s++;
00103
00104 if( strmatch(next, "sinh" ) ) d= sinh(d);
00105 else if( strmatch(next, "cosh" ) ) d= cosh(d);
00106 else if( strmatch(next, "tanh" ) ) d= tanh(d);
00107 else if( strmatch(next, "sin" ) ) d= sin(d);
00108 else if( strmatch(next, "cos" ) ) d= cos(d);
00109 else if( strmatch(next, "tan" ) ) d= tan(d);
00110 else if( strmatch(next, "exp" ) ) d= exp(d);
00111 else if( strmatch(next, "log" ) ) d= log(d);
00112 else if( strmatch(next, "squish") ) d= 1/(1+exp(4*d));
00113 else if( strmatch(next, "gauss" ) ) d= exp(-d*d/2)/sqrt(2*M_PI);
00114 else if( strmatch(next, "abs" ) ) d= fabs(d);
00115 else if( strmatch(next, "max" ) ) d= d > d2 ? d : d2;
00116 else if( strmatch(next, "min" ) ) d= d < d2 ? d : d2;
00117 else if( strmatch(next, "gt" ) ) d= d > d2 ? 1.0 : 0.0;
00118 else if( strmatch(next, "gte" ) ) d= d >= d2 ? 1.0 : 0.0;
00119 else if( strmatch(next, "lt" ) ) d= d > d2 ? 0.0 : 1.0;
00120 else if( strmatch(next, "lte" ) ) d= d >= d2 ? 0.0 : 1.0;
00121 else if( strmatch(next, "eq" ) ) d= d == d2 ? 1.0 : 0.0;
00122 else if( strmatch(next, "(" ) ) d= d;
00123
00124
00125 else{
00126 for(i=0; p->func1_name && p->func1_name[i]; i++){
00127 if(strmatch(next, p->func1_name[i])){
00128 return p->func1[i](p->opaque, d);
00129 }
00130 }
00131
00132 for(i=0; p->func2_name && p->func2_name[i]; i++){
00133 if(strmatch(next, p->func2_name[i])){
00134 return p->func2[i](p->opaque, d, d2);
00135 }
00136 }
00137
00138 av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next);
00139 return NAN;
00140 }
00141
00142 return d;
00143 }
00144
00145 static double evalPow(Parser *p){
00146 int sign= (*p->s == '+') - (*p->s == '-');
00147 p->s += sign&1;
00148 return (sign|1) * evalPrimary(p);
00149 }
00150
00151 static double evalFactor(Parser *p){
00152 double ret= evalPow(p);
00153 while(p->s[0]=='^'){
00154 p->s++;
00155 ret= pow(ret, evalPow(p));
00156 }
00157 return ret;
00158 }
00159
00160 static double evalTerm(Parser *p){
00161 double ret= evalFactor(p);
00162 while(p->s[0]=='*' || p->s[0]=='/'){
00163 if(*p->s++ == '*') ret*= evalFactor(p);
00164 else ret/= evalFactor(p);
00165 }
00166 return ret;
00167 }
00168
00169 static double evalExpression(Parser *p){
00170 double ret= 0;
00171
00172 if(p->stack_index <= 0)
00173 return NAN;
00174 p->stack_index--;
00175
00176 do{
00177 ret += evalTerm(p);
00178 }while(*p->s == '+' || *p->s == '-');
00179
00180 p->stack_index++;
00181
00182 return ret;
00183 }
00184
00185 double ff_eval(char *s, double *const_value, const char **const_name,
00186 double (**func1)(void *, double), const char **func1_name,
00187 double (**func2)(void *, double, double), char **func2_name,
00188 void *opaque){
00189 Parser p;
00190
00191 p.stack_index=100;
00192 p.s= s;
00193 p.const_value= const_value;
00194 p.const_name = const_name;
00195 p.func1 = func1;
00196 p.func1_name = func1_name;
00197 p.func2 = func2;
00198 p.func2_name = func2_name;
00199 p.opaque = opaque;
00200
00201 return evalExpression(&p);
00202 }
00203
00204 #ifdef TEST
00205 #undef printf
00206 static double const_values[]={
00207 M_PI,
00208 M_E,
00209 0
00210 };
00211 static const char *const_names[]={
00212 "PI",
00213 "E",
00214 0
00215 };
00216 main(){
00217 int i;
00218 printf("%f == 12.7\n", ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL));
00219
00220 for(i=0; i<1050; i++){
00221 START_TIMER
00222 ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL);
00223 STOP_TIMER("ff_eval")
00224 }
00225 }
00226 #endif