2 * simple arithmetic expression evaluator
4 * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * simple arithmetic expression evaluator.
26 * see http://joe.hotchkiss.com/programming/eval/eval.html
30 #include "mpegvideo.h"
42 #define M_PI 3.14159265358979323846
45 typedef struct Parser
{
49 const char **const_name
; // NULL terminated
50 double (**func1
)(void *, double a
); // NULL terminated
51 const char **func1_name
; // NULL terminated
52 double (**func2
)(void *, double a
, double b
); // NULL terminated
53 char **func2_name
; // NULL terminated
57 static double evalExpression(Parser
*p
);
59 static int strmatch(const char *s
, const char *prefix
){
61 for(i
=0; prefix
[i
]; i
++){
62 if(prefix
[i
] != s
[i
]) return 0;
67 static double evalPrimary(Parser
*p
){
73 d
= strtod(p
->s
, &next
);
80 for(i
=0; p
->const_name
&& p
->const_name
[i
]; i
++){
81 if(strmatch(p
->s
, p
->const_name
[i
])){
82 p
->s
+= strlen(p
->const_name
[i
]);
83 return p
->const_value
[i
];
87 p
->s
= strchr(p
->s
, '(');
89 av_log(NULL
, AV_LOG_ERROR
, "Parser: missing ( in \"%s\"\n", next
);
96 d2
= evalExpression(p
);
99 av_log(NULL
, AV_LOG_ERROR
, "Parser: missing ) in \"%s\"\n", next
);
104 if( strmatch(next
, "sinh" ) ) d
= sinh(d
);
105 else if( strmatch(next
, "cosh" ) ) d
= cosh(d
);
106 else if( strmatch(next
, "tanh" ) ) d
= tanh(d
);
107 else if( strmatch(next
, "sin" ) ) d
= sin(d
);
108 else if( strmatch(next
, "cos" ) ) d
= cos(d
);
109 else if( strmatch(next
, "tan" ) ) d
= tan(d
);
110 else if( strmatch(next
, "exp" ) ) d
= exp(d
);
111 else if( strmatch(next
, "log" ) ) d
= log(d
);
112 else if( strmatch(next
, "squish") ) d
= 1/(1+exp(4*d
));
113 else if( strmatch(next
, "gauss" ) ) d
= exp(-d
*d
/2)/sqrt(2*M_PI
);
114 else if( strmatch(next
, "abs" ) ) d
= fabs(d
);
115 else if( strmatch(next
, "max" ) ) d
= d
> d2
? d
: d2
;
116 else if( strmatch(next
, "min" ) ) d
= d
< d2
? d
: d2
;
117 else if( strmatch(next
, "gt" ) ) d
= d
> d2
? 1.0 : 0.0;
118 else if( strmatch(next
, "gte" ) ) d
= d
>= d2
? 1.0 : 0.0;
119 else if( strmatch(next
, "lt" ) ) d
= d
> d2
? 0.0 : 1.0;
120 else if( strmatch(next
, "lte" ) ) d
= d
>= d2
? 0.0 : 1.0;
121 else if( strmatch(next
, "eq" ) ) d
= d
== d2
? 1.0 : 0.0;
122 else if( strmatch(next
, "(" ) ) d
= d
;
123 // else if( strmatch(next, "l1" ) ) d= 1 + d2*(d - 1);
124 // else if( strmatch(next, "sq01" ) ) d= (d >= 0.0 && d <=1.0) ? 1.0 : 0.0;
126 for(i
=0; p
->func1_name
&& p
->func1_name
[i
]; i
++){
127 if(strmatch(next
, p
->func1_name
[i
])){
128 return p
->func1
[i
](p
->opaque
, d
);
132 for(i
=0; p
->func2_name
&& p
->func2_name
[i
]; i
++){
133 if(strmatch(next
, p
->func2_name
[i
])){
134 return p
->func2
[i
](p
->opaque
, d
, d2
);
138 av_log(NULL
, AV_LOG_ERROR
, "Parser: unknown function in \"%s\"\n", next
);
145 static double evalPow(Parser
*p
){
146 int sign
= (*p
->s
== '+') - (*p
->s
== '-');
148 return (sign
|1) * evalPrimary(p
);
151 static double evalFactor(Parser
*p
){
152 double ret
= evalPow(p
);
155 ret
= pow(ret
, evalPow(p
));
160 static double evalTerm(Parser
*p
){
161 double ret
= evalFactor(p
);
162 while(p
->s
[0]=='*' || p
->s
[0]=='/'){
163 if(*p
->s
++ == '*') ret
*= evalFactor(p
);
164 else ret
/= evalFactor(p
);
169 static double evalExpression(Parser
*p
){
172 if(p
->stack_index
<= 0) //protect against stack overflows
178 }while(*p
->s
== '+' || *p
->s
== '-');
185 double ff_eval(char *s
, double *const_value
, const char **const_name
,
186 double (**func1
)(void *, double), const char **func1_name
,
187 double (**func2
)(void *, double, double), char **func2_name
,
193 p
.const_value
= const_value
;
194 p
.const_name
= const_name
;
196 p
.func1_name
= func1_name
;
198 p
.func2_name
= func2_name
;
201 return evalExpression(&p
);
206 static double const_values
[]={
211 static const char *const_names
[]={
218 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
));
220 for(i
=0; i
<1050; i
++){
222 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
);
223 STOP_TIMER("ff_eval")