2 * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 * simple arithmetic expression evaluator.
26 * see http://joe.hotchkiss.com/programming/eval/eval.html
29 #include "libavutil/avutil.h"
32 typedef struct Parser
{
35 const double *const_value
;
36 const char * const *const_name
; // NULL terminated
37 double (* const *func1
)(void *, double a
); // NULL terminated
38 const char * const *func1_name
; // NULL terminated
39 double (* const *func2
)(void *, double a
, double b
); // NULL terminated
40 const char * const *func2_name
; // NULL terminated
47 static const int8_t si_prefixes
['z' - 'E' + 1]={
70 double av_strtod(const char *numstr
, char **tail
) {
73 d
= strtod(numstr
, &next
);
74 /* if parsing succeeded, check for and interpret postfixes */
77 if(*next
>= 'E' && *next
<= 'z'){
78 int e
= si_prefixes
[*next
- 'E'];
95 /* if requested, fill in tail with the position after the last parsed
102 static int strmatch(const char *s
, const char *prefix
){
104 for(i
=0; prefix
[i
]; i
++){
105 if(prefix
[i
] != s
[i
]) return 0;
112 e_value
, e_const
, e_func0
, e_func1
, e_func2
,
113 e_squish
, e_gauss
, e_ld
,
114 e_mod
, e_max
, e_min
, e_eq
, e_gt
, e_gte
,
115 e_pow
, e_mul
, e_div
, e_add
,
116 e_last
, e_st
, e_while
,
118 double value
; // is sign in other types
121 double (*func0
)(double);
122 double (*func1
)(void *, double);
123 double (*func2
)(void *, double, double);
125 struct AVExpr
*param
[2];
128 static double eval_expr(Parser
* p
, AVExpr
* e
) {
130 case e_value
: return e
->value
;
131 case e_const
: return e
->value
* p
->const_value
[e
->a
.const_index
];
132 case e_func0
: return e
->value
* e
->a
.func0(eval_expr(p
, e
->param
[0]));
133 case e_func1
: return e
->value
* e
->a
.func1(p
->opaque
, eval_expr(p
, e
->param
[0]));
134 case e_func2
: return e
->value
* e
->a
.func2(p
->opaque
, eval_expr(p
, e
->param
[0]), eval_expr(p
, e
->param
[1]));
135 case e_squish
: return 1/(1+exp(4*eval_expr(p
, e
->param
[0])));
136 case e_gauss
: { double d
= eval_expr(p
, e
->param
[0]); return exp(-d
*d
/2)/sqrt(2*M_PI
); }
137 case e_ld
: return e
->value
* p
->var
[av_clip(eval_expr(p
, e
->param
[0]), 0, VARS
-1)];
140 while(eval_expr(p
, e
->param
[0]))
141 d
=eval_expr(p
, e
->param
[1]);
145 double d
= eval_expr(p
, e
->param
[0]);
146 double d2
= eval_expr(p
, e
->param
[1]);
148 case e_mod
: return e
->value
* (d
- floor(d
/d2
)*d2
);
149 case e_max
: return e
->value
* (d
> d2 ? d
: d2
);
150 case e_min
: return e
->value
* (d
< d2 ? d
: d2
);
151 case e_eq
: return e
->value
* (d
== d2 ?
1.0 : 0.0);
152 case e_gt
: return e
->value
* (d
> d2 ?
1.0 : 0.0);
153 case e_gte
: return e
->value
* (d
>= d2 ?
1.0 : 0.0);
154 case e_pow
: return e
->value
* pow(d
, d2
);
155 case e_mul
: return e
->value
* (d
* d2
);
156 case e_div
: return e
->value
* (d
/ d2
);
157 case e_add
: return e
->value
* (d
+ d2
);
158 case e_last
:return e
->value
* d2
;
159 case e_st
: return e
->value
* (p
->var
[av_clip(d
, 0, VARS
-1)]= d2
);
166 static AVExpr
* parse_expr(Parser
*p
);
168 void ff_free_expr(AVExpr
* e
) {
170 ff_free_expr(e
->param
[0]);
171 ff_free_expr(e
->param
[1]);
175 static AVExpr
* parse_primary(Parser
*p
) {
176 AVExpr
* d
= av_mallocz(sizeof(AVExpr
));
184 d
->value
= av_strtod(p
->s
, &next
);
192 /* named constants */
193 for(i
=0; p
->const_name
&& p
->const_name
[i
]; i
++){
194 if(strmatch(p
->s
, p
->const_name
[i
])){
195 p
->s
+= strlen(p
->const_name
[i
]);
197 d
->a
.const_index
= i
;
202 p
->s
= strchr(p
->s
, '(');
204 *p
->error
= "undefined constant or missing (";
210 if (*next
== '(') { // special case do-nothing
214 *p
->error
= "missing )";
221 d
->param
[0] = parse_expr(p
);
224 d
->param
[1] = parse_expr(p
);
227 *p
->error
= "missing )";
234 if( strmatch(next
, "sinh" ) ) d
->a
.func0
= sinh
;
235 else if( strmatch(next
, "cosh" ) ) d
->a
.func0
= cosh
;
236 else if( strmatch(next
, "tanh" ) ) d
->a
.func0
= tanh
;
237 else if( strmatch(next
, "sin" ) ) d
->a
.func0
= sin
;
238 else if( strmatch(next
, "cos" ) ) d
->a
.func0
= cos
;
239 else if( strmatch(next
, "tan" ) ) d
->a
.func0
= tan
;
240 else if( strmatch(next
, "atan" ) ) d
->a
.func0
= atan
;
241 else if( strmatch(next
, "asin" ) ) d
->a
.func0
= asin
;
242 else if( strmatch(next
, "acos" ) ) d
->a
.func0
= acos
;
243 else if( strmatch(next
, "exp" ) ) d
->a
.func0
= exp
;
244 else if( strmatch(next
, "log" ) ) d
->a
.func0
= log
;
245 else if( strmatch(next
, "abs" ) ) d
->a
.func0
= fabs
;
246 else if( strmatch(next
, "squish") ) d
->type
= e_squish
;
247 else if( strmatch(next
, "gauss" ) ) d
->type
= e_gauss
;
248 else if( strmatch(next
, "mod" ) ) d
->type
= e_mod
;
249 else if( strmatch(next
, "max" ) ) d
->type
= e_max
;
250 else if( strmatch(next
, "min" ) ) d
->type
= e_min
;
251 else if( strmatch(next
, "eq" ) ) d
->type
= e_eq
;
252 else if( strmatch(next
, "gte" ) ) d
->type
= e_gte
;
253 else if( strmatch(next
, "gt" ) ) d
->type
= e_gt
;
254 else if( strmatch(next
, "lte" ) ) { AVExpr
* tmp
= d
->param
[1]; d
->param
[1] = d
->param
[0]; d
->param
[0] = tmp
; d
->type
= e_gt
; }
255 else if( strmatch(next
, "lt" ) ) { AVExpr
* tmp
= d
->param
[1]; d
->param
[1] = d
->param
[0]; d
->param
[0] = tmp
; d
->type
= e_gte
; }
256 else if( strmatch(next
, "ld" ) ) d
->type
= e_ld
;
257 else if( strmatch(next
, "st" ) ) d
->type
= e_st
;
258 else if( strmatch(next
, "while" ) ) d
->type
= e_while
;
260 for(i
=0; p
->func1_name
&& p
->func1_name
[i
]; i
++){
261 if(strmatch(next
, p
->func1_name
[i
])){
262 d
->a
.func1
= p
->func1
[i
];
268 for(i
=0; p
->func2_name
&& p
->func2_name
[i
]; i
++){
269 if(strmatch(next
, p
->func2_name
[i
])){
270 d
->a
.func2
= p
->func2
[i
];
276 *p
->error
= "unknown function";
284 static AVExpr
* new_eval_expr(int type
, int value
, AVExpr
*p0
, AVExpr
*p1
){
285 AVExpr
* e
= av_mallocz(sizeof(AVExpr
));
295 static AVExpr
* parse_pow(Parser
*p
, int *sign
){
296 *sign
= (*p
->s
== '+') - (*p
->s
== '-');
298 return parse_primary(p
);
301 static AVExpr
* parse_factor(Parser
*p
){
303 AVExpr
* e
= parse_pow(p
, &sign
);
306 e
= new_eval_expr(e_pow
, 1, e
, parse_pow(p
, &sign2
));
309 if (e
->param
[1]) e
->param
[1]->value
*= (sign2
|1);
311 if (e
) e
->value
*= (sign
|1);
315 static AVExpr
* parse_term(Parser
*p
){
316 AVExpr
* e
= parse_factor(p
);
317 while(p
->s
[0]=='*' || p
->s
[0]=='/'){
319 e
= new_eval_expr(c
== '*' ? e_mul
: e_div
, 1, e
, parse_factor(p
));
326 static AVExpr
* parse_subexpr(Parser
*p
) {
327 AVExpr
* e
= parse_term(p
);
328 while(*p
->s
== '+' || *p
->s
== '-') {
329 e
= new_eval_expr(e_add
, 1, e
, parse_term(p
));
337 static AVExpr
* parse_expr(Parser
*p
) {
340 if(p
->stack_index
<= 0) //protect against stack overflows
344 e
= parse_subexpr(p
);
346 while(*p
->s
== ';') {
348 e
= new_eval_expr(e_last
, 1, e
, parse_subexpr(p
));
358 static int verify_expr(AVExpr
* e
) {
362 case e_const
: return 1;
367 case e_gauss
: return verify_expr(e
->param
[0]);
368 default: return verify_expr(e
->param
[0]) && verify_expr(e
->param
[1]);
372 AVExpr
*ff_parse_expr(const char *s
,
373 const char * const *const_name
,
374 const char * const *func1_name
, double (* const *func1
)(void *, double),
375 const char * const *func2_name
, double (* const *func2
)(void *, double, double),
379 char *w
= av_malloc(strlen(s
) + 1);
386 if (!isspace(*s
++)) *wp
++ = s
[-1];
391 p
.const_name
= const_name
;
393 p
.func1_name
= func1_name
;
395 p
.func2_name
= func2_name
;
399 if (!verify_expr(e
)) {
408 double ff_eval_expr(AVExpr
* e
, const double *const_value
, void *opaque
) {
411 p
.const_value
= const_value
;
413 return eval_expr(&p
, e
);
416 double ff_parse_and_eval_expr(const char *s
,
417 const char * const *const_name
, const double *const_value
,
418 const char * const *func1_name
, double (* const *func1
)(void *, double),
419 const char * const *func2_name
, double (* const *func2
)(void *, double, double),
420 void *opaque
, const char **error
){
421 AVExpr
*e
= ff_parse_expr(s
, const_name
, func1_name
, func1
, func2_name
, func2
, error
);
424 d
= ff_eval_expr(e
, const_value
, opaque
);
431 static double const_values
[]={
436 static const char *const_names
[]={
443 printf("%f == 12.7\n", ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names
, const_values
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
));
444 printf("%f == 0.931322575\n", ff_parse_and_eval_expr("80G/80Gi", const_names
, const_values
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
));
446 for(i
=0; i
<1050; i
++){
448 ff_parse_and_eval_expr("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_names
, const_values
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
449 STOP_TIMER("ff_parse_and_eval_expr")