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
30 #include "attributes.h"
35 #include "mathematics.h"
40 typedef struct Parser
{
44 const double *const_values
;
45 const char * const *const_names
; // NULL terminated
46 double (* const *funcs1
)(void *, double a
); // NULL terminated
47 const char * const *func1_names
; // NULL terminated
48 double (* const *funcs2
)(void *, double a
, double b
); // NULL terminated
49 const char * const *func2_names
; // NULL terminated
57 static const AVClass eval_class
= { "Eval", av_default_item_name
, NULL
, LIBAVUTIL_VERSION_INT
, offsetof(Parser
,log_offset
), offsetof(Parser
,log_ctx
) };
59 static const int8_t si_prefixes
['z' - 'E' + 1] = {
89 { "QP2LAMBDA", FF_QP2LAMBDA
},
92 double av_strtod(const char *numstr
, char **tail
)
96 if(numstr
[0]=='0' && (numstr
[1]|0x20)=='x') {
97 d
= strtoul(numstr
, &next
, 16);
99 d
= strtod(numstr
, &next
);
100 /* if parsing succeeded, check for and interpret postfixes */
102 if (next
[0] == 'd' && next
[1] == 'B') {
103 /* treat dB as decibels instead of decibytes */
106 } else if (*next
>= 'E' && *next
<= 'z') {
107 int e
= si_prefixes
[*next
- 'E'];
109 if (next
[1] == 'i') {
124 /* if requested, fill in tail with the position after the last parsed
131 #define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_')
133 static int strmatch(const char *s
, const char *prefix
)
136 for (i
=0; prefix
[i
]; i
++) {
137 if (prefix
[i
] != s
[i
]) return 0;
139 /* return 1 only if the s identifier is terminated */
140 return !IS_IDENTIFIER_CHAR(s
[i
]);
145 e_value
, e_const
, e_func0
, e_func1
, e_func2
,
146 e_squish
, e_gauss
, e_ld
, e_isnan
, e_isinf
,
147 e_mod
, e_max
, e_min
, e_eq
, e_gt
, e_gte
, e_lte
, e_lt
,
148 e_pow
, e_mul
, e_div
, e_add
,
149 e_last
, e_st
, e_while
, e_taylor
, e_root
, e_floor
, e_ceil
, e_trunc
,
150 e_sqrt
, e_not
, e_random
, e_hypot
, e_gcd
,
151 e_if
, e_ifnot
, e_print
, e_bitand
, e_bitor
, e_between
, e_clip
153 double value
; // is sign in other types
156 double (*func0
)(double);
157 double (*func1
)(void *, double);
158 double (*func2
)(void *, double, double);
160 struct AVExpr
*param
[3];
164 static double etime(double v
)
166 return av_gettime() * 0.000001;
169 static double eval_expr(Parser
*p
, AVExpr
*e
)
172 case e_value
: return e
->value
;
173 case e_const
: return e
->value
* p
->const_values
[e
->a
.const_index
];
174 case e_func0
: return e
->value
* e
->a
.func0(eval_expr(p
, e
->param
[0]));
175 case e_func1
: return e
->value
* e
->a
.func1(p
->opaque
, eval_expr(p
, e
->param
[0]));
176 case e_func2
: return e
->value
* e
->a
.func2(p
->opaque
, eval_expr(p
, e
->param
[0]), eval_expr(p
, e
->param
[1]));
177 case e_squish
: return 1/(1+exp(4*eval_expr(p
, e
->param
[0])));
178 case e_gauss
: { double d
= eval_expr(p
, e
->param
[0]); return exp(-d
*d
/2)/sqrt(2*M_PI
); }
179 case e_ld
: return e
->value
* p
->var
[av_clip(eval_expr(p
, e
->param
[0]), 0, VARS
-1)];
180 case e_isnan
: return e
->value
* !!isnan(eval_expr(p
, e
->param
[0]));
181 case e_isinf
: return e
->value
* !!isinf(eval_expr(p
, e
->param
[0]));
182 case e_floor
: return e
->value
* floor(eval_expr(p
, e
->param
[0]));
183 case e_ceil
: return e
->value
* ceil (eval_expr(p
, e
->param
[0]));
184 case e_trunc
: return e
->value
* trunc(eval_expr(p
, e
->param
[0]));
185 case e_sqrt
: return e
->value
* sqrt (eval_expr(p
, e
->param
[0]));
186 case e_not
: return e
->value
* (eval_expr(p
, e
->param
[0]) == 0);
187 case e_if
: return e
->value
* (eval_expr(p
, e
->param
[0]) ? eval_expr(p
, e
->param
[1]) :
188 e
->param
[2] ? eval_expr(p
, e
->param
[2]) : 0);
189 case e_ifnot
: return e
->value
* (!eval_expr(p
, e
->param
[0]) ? eval_expr(p
, e
->param
[1]) :
190 e
->param
[2] ? eval_expr(p
, e
->param
[2]) : 0);
192 double x
= eval_expr(p
, e
->param
[0]);
193 double min
= eval_expr(p
, e
->param
[1]), max
= eval_expr(p
, e
->param
[2]);
194 if (isnan(min
) || isnan(max
) || isnan(x
) || min
> max
)
196 return e
->value
* av_clipd(eval_expr(p
, e
->param
[0]), min
, max
);
199 double d
= eval_expr(p
, e
->param
[0]);
200 return e
->value
* (d
>= eval_expr(p
, e
->param
[1]) &&
201 d
<= eval_expr(p
, e
->param
[2]));
204 double x
= eval_expr(p
, e
->param
[0]);
205 int level
= e
->param
[1] ? av_clip(eval_expr(p
, e
->param
[1]), INT_MIN
, INT_MAX
) : AV_LOG_INFO
;
206 av_log(p
, level
, "%f\n", x
);
210 int idx
= av_clip(eval_expr(p
, e
->param
[0]), 0, VARS
-1);
211 uint64_t r
= isnan(p
->var
[idx
]) ? 0 : p
->var
[idx
];
212 r
= r
*1664525+1013904223;
214 return e
->value
* (r
* (1.0/UINT64_MAX
));
218 while (eval_expr(p
, e
->param
[0]))
219 d
=eval_expr(p
, e
->param
[1]);
223 double t
= 1, d
= 0, v
;
224 double x
= eval_expr(p
, e
->param
[1]);
225 int id
= e
->param
[2] ? av_clip(eval_expr(p
, e
->param
[2]), 0, VARS
-1) : 0;
227 double var0
= p
->var
[id
];
228 for(i
=0; i
<1000; i
++) {
231 v
= eval_expr(p
, e
->param
[0]);
242 double low
= -1, high
= -1, v
, low_v
= -DBL_MAX
, high_v
= DBL_MAX
;
243 double var0
= p
->var
[0];
244 double x_max
= eval_expr(p
, e
->param
[1]);
245 for(i
=-1; i
<1024; i
++) {
247 p
->var
[0] = av_reverse
[i
&255]*x_max
/255;
249 p
->var
[0] = x_max
*pow(0.9, i
-255);
250 if (i
&1) p
->var
[0] *= -1;
251 if (i
&2) p
->var
[0] += low
;
252 else p
->var
[0] += high
;
254 v
= eval_expr(p
, e
->param
[0]);
255 if (v
<=0 && v
>low_v
) {
259 if (v
>=0 && v
<high_v
) {
263 if (low
>=0 && high
>=0){
264 for (j
=0; j
<1000; j
++) {
265 p
->var
[0] = (low
+high
)*0.5;
266 if (low
== p
->var
[0] || high
== p
->var
[0])
268 v
= eval_expr(p
, e
->param
[0]);
269 if (v
<=0) low
= p
->var
[0];
270 if (v
>=0) high
= p
->var
[0];
280 return -low_v
<high_v
? low
: high
;
283 double d
= eval_expr(p
, e
->param
[0]);
284 double d2
= eval_expr(p
, e
->param
[1]);
286 case e_mod
: return e
->value
* (d
- floor((!CONFIG_FTRAPV
|| d2
) ? d
/ d2
: d
* INFINITY
) * d2
);
287 case e_gcd
: return e
->value
* av_gcd(d
,d2
);
288 case e_max
: return e
->value
* (d
> d2
? d
: d2
);
289 case e_min
: return e
->value
* (d
< d2
? d
: d2
);
290 case e_eq
: return e
->value
* (d
== d2
? 1.0 : 0.0);
291 case e_gt
: return e
->value
* (d
> d2
? 1.0 : 0.0);
292 case e_gte
: return e
->value
* (d
>= d2
? 1.0 : 0.0);
293 case e_lt
: return e
->value
* (d
< d2
? 1.0 : 0.0);
294 case e_lte
: return e
->value
* (d
<= d2
? 1.0 : 0.0);
295 case e_pow
: return e
->value
* pow(d
, d2
);
296 case e_mul
: return e
->value
* (d
* d2
);
297 case e_div
: return e
->value
* ((!CONFIG_FTRAPV
|| d2
) ? (d
/ d2
) : d
* INFINITY
);
298 case e_add
: return e
->value
* (d
+ d2
);
299 case e_last
:return e
->value
* d2
;
300 case e_st
: return e
->value
* (p
->var
[av_clip(d
, 0, VARS
-1)]= d2
);
301 case e_hypot
:return e
->value
* (sqrt(d
*d
+ d2
*d2
));
302 case e_bitand
: return isnan(d
) || isnan(d2
) ? NAN
: e
->value
* ((long int)d
& (long int)d2
);
303 case e_bitor
: return isnan(d
) || isnan(d2
) ? NAN
: e
->value
* ((long int)d
| (long int)d2
);
310 static int parse_expr(AVExpr
**e
, Parser
*p
);
312 void av_expr_free(AVExpr
*e
)
315 av_expr_free(e
->param
[0]);
316 av_expr_free(e
->param
[1]);
317 av_expr_free(e
->param
[2]);
322 static int parse_primary(AVExpr
**e
, Parser
*p
)
324 AVExpr
*d
= av_mallocz(sizeof(AVExpr
));
325 char *next
= p
->s
, *s0
= p
->s
;
329 return AVERROR(ENOMEM
);
332 d
->value
= av_strtod(p
->s
, &next
);
341 /* named constants */
342 for (i
=0; p
->const_names
&& p
->const_names
[i
]; i
++) {
343 if (strmatch(p
->s
, p
->const_names
[i
])) {
344 p
->s
+= strlen(p
->const_names
[i
]);
346 d
->a
.const_index
= i
;
351 for (i
= 0; i
< FF_ARRAY_ELEMS(constants
); i
++) {
352 if (strmatch(p
->s
, constants
[i
].name
)) {
353 p
->s
+= strlen(constants
[i
].name
);
355 d
->value
= constants
[i
].value
;
361 p
->s
= strchr(p
->s
, '(');
363 av_log(p
, AV_LOG_ERROR
, "Undefined constant or missing '(' in '%s'\n", s0
);
366 return AVERROR(EINVAL
);
369 if (*next
== '(') { // special case do-nothing
371 if ((ret
= parse_expr(&d
, p
)) < 0)
373 if (p
->s
[0] != ')') {
374 av_log(p
, AV_LOG_ERROR
, "Missing ')' in '%s'\n", s0
);
376 return AVERROR(EINVAL
);
382 if ((ret
= parse_expr(&(d
->param
[0]), p
)) < 0) {
388 parse_expr(&d
->param
[1], p
);
392 parse_expr(&d
->param
[2], p
);
394 if (p
->s
[0] != ')') {
395 av_log(p
, AV_LOG_ERROR
, "Missing ')' or too many args in '%s'\n", s0
);
397 return AVERROR(EINVAL
);
402 if (strmatch(next
, "sinh" )) d
->a
.func0
= sinh
;
403 else if (strmatch(next
, "cosh" )) d
->a
.func0
= cosh
;
404 else if (strmatch(next
, "tanh" )) d
->a
.func0
= tanh
;
405 else if (strmatch(next
, "sin" )) d
->a
.func0
= sin
;
406 else if (strmatch(next
, "cos" )) d
->a
.func0
= cos
;
407 else if (strmatch(next
, "tan" )) d
->a
.func0
= tan
;
408 else if (strmatch(next
, "atan" )) d
->a
.func0
= atan
;
409 else if (strmatch(next
, "asin" )) d
->a
.func0
= asin
;
410 else if (strmatch(next
, "acos" )) d
->a
.func0
= acos
;
411 else if (strmatch(next
, "exp" )) d
->a
.func0
= exp
;
412 else if (strmatch(next
, "log" )) d
->a
.func0
= log
;
413 else if (strmatch(next
, "abs" )) d
->a
.func0
= fabs
;
414 else if (strmatch(next
, "time" )) d
->a
.func0
= etime
;
415 else if (strmatch(next
, "squish")) d
->type
= e_squish
;
416 else if (strmatch(next
, "gauss" )) d
->type
= e_gauss
;
417 else if (strmatch(next
, "mod" )) d
->type
= e_mod
;
418 else if (strmatch(next
, "max" )) d
->type
= e_max
;
419 else if (strmatch(next
, "min" )) d
->type
= e_min
;
420 else if (strmatch(next
, "eq" )) d
->type
= e_eq
;
421 else if (strmatch(next
, "gte" )) d
->type
= e_gte
;
422 else if (strmatch(next
, "gt" )) d
->type
= e_gt
;
423 else if (strmatch(next
, "lte" )) d
->type
= e_lte
;
424 else if (strmatch(next
, "lt" )) d
->type
= e_lt
;
425 else if (strmatch(next
, "ld" )) d
->type
= e_ld
;
426 else if (strmatch(next
, "isnan" )) d
->type
= e_isnan
;
427 else if (strmatch(next
, "isinf" )) d
->type
= e_isinf
;
428 else if (strmatch(next
, "st" )) d
->type
= e_st
;
429 else if (strmatch(next
, "while" )) d
->type
= e_while
;
430 else if (strmatch(next
, "taylor")) d
->type
= e_taylor
;
431 else if (strmatch(next
, "root" )) d
->type
= e_root
;
432 else if (strmatch(next
, "floor" )) d
->type
= e_floor
;
433 else if (strmatch(next
, "ceil" )) d
->type
= e_ceil
;
434 else if (strmatch(next
, "trunc" )) d
->type
= e_trunc
;
435 else if (strmatch(next
, "sqrt" )) d
->type
= e_sqrt
;
436 else if (strmatch(next
, "not" )) d
->type
= e_not
;
437 else if (strmatch(next
, "pow" )) d
->type
= e_pow
;
438 else if (strmatch(next
, "print" )) d
->type
= e_print
;
439 else if (strmatch(next
, "random")) d
->type
= e_random
;
440 else if (strmatch(next
, "hypot" )) d
->type
= e_hypot
;
441 else if (strmatch(next
, "gcd" )) d
->type
= e_gcd
;
442 else if (strmatch(next
, "if" )) d
->type
= e_if
;
443 else if (strmatch(next
, "ifnot" )) d
->type
= e_ifnot
;
444 else if (strmatch(next
, "bitand")) d
->type
= e_bitand
;
445 else if (strmatch(next
, "bitor" )) d
->type
= e_bitor
;
446 else if (strmatch(next
, "between"))d
->type
= e_between
;
447 else if (strmatch(next
, "clip" )) d
->type
= e_clip
;
449 for (i
=0; p
->func1_names
&& p
->func1_names
[i
]; i
++) {
450 if (strmatch(next
, p
->func1_names
[i
])) {
451 d
->a
.func1
= p
->funcs1
[i
];
458 for (i
=0; p
->func2_names
&& p
->func2_names
[i
]; i
++) {
459 if (strmatch(next
, p
->func2_names
[i
])) {
460 d
->a
.func2
= p
->funcs2
[i
];
467 av_log(p
, AV_LOG_ERROR
, "Unknown function in '%s'\n", s0
);
469 return AVERROR(EINVAL
);
476 static AVExpr
*make_eval_expr(int type
, int value
, AVExpr
*p0
, AVExpr
*p1
)
478 AVExpr
*e
= av_mallocz(sizeof(AVExpr
));
488 static int parse_pow(AVExpr
**e
, Parser
*p
, int *sign
)
490 *sign
= (*p
->s
== '+') - (*p
->s
== '-');
492 return parse_primary(e
, p
);
495 static int parse_dB(AVExpr
**e
, Parser
*p
, int *sign
)
497 /* do not filter out the negative sign when parsing a dB value.
498 for example, -3dB is not the same as -(3dB) */
501 double av_unused ignored
= strtod(p
->s
, &next
);
502 if (next
!= p
->s
&& next
[0] == 'd' && next
[1] == 'B') {
504 return parse_primary(e
, p
);
507 return parse_pow(e
, p
, sign
);
510 static int parse_factor(AVExpr
**e
, Parser
*p
)
512 int sign
, sign2
, ret
;
513 AVExpr
*e0
, *e1
, *e2
;
514 if ((ret
= parse_dB(&e0
, p
, &sign
)) < 0)
519 if ((ret
= parse_dB(&e2
, p
, &sign2
)) < 0) {
523 e0
= make_eval_expr(e_pow
, 1, e1
, e2
);
527 return AVERROR(ENOMEM
);
529 if (e0
->param
[1]) e0
->param
[1]->value
*= (sign2
|1);
531 if (e0
) e0
->value
*= (sign
|1);
537 static int parse_term(AVExpr
**e
, Parser
*p
)
540 AVExpr
*e0
, *e1
, *e2
;
541 if ((ret
= parse_factor(&e0
, p
)) < 0)
543 while (p
->s
[0]=='*' || p
->s
[0]=='/') {
546 if ((ret
= parse_factor(&e2
, p
)) < 0) {
550 e0
= make_eval_expr(c
== '*' ? e_mul
: e_div
, 1, e1
, e2
);
554 return AVERROR(ENOMEM
);
561 static int parse_subexpr(AVExpr
**e
, Parser
*p
)
564 AVExpr
*e0
, *e1
, *e2
;
565 if ((ret
= parse_term(&e0
, p
)) < 0)
567 while (*p
->s
== '+' || *p
->s
== '-') {
569 if ((ret
= parse_term(&e2
, p
)) < 0) {
573 e0
= make_eval_expr(e_add
, 1, e1
, e2
);
577 return AVERROR(ENOMEM
);
585 static int parse_expr(AVExpr
**e
, Parser
*p
)
588 AVExpr
*e0
, *e1
, *e2
;
589 if (p
->stack_index
<= 0) //protect against stack overflows
590 return AVERROR(EINVAL
);
593 if ((ret
= parse_subexpr(&e0
, p
)) < 0)
595 while (*p
->s
== ';') {
598 if ((ret
= parse_subexpr(&e2
, p
)) < 0) {
602 e0
= make_eval_expr(e_last
, 1, e1
, e2
);
606 return AVERROR(ENOMEM
);
615 static int verify_expr(AVExpr
*e
)
620 case e_const
: return 1;
634 return verify_expr(e
->param
[0]) && !e
->param
[1];
636 return verify_expr(e
->param
[0])
637 && (!e
->param
[1] || verify_expr(e
->param
[1]));
641 return verify_expr(e
->param
[0]) && verify_expr(e
->param
[1])
642 && (!e
->param
[2] || verify_expr(e
->param
[2]));
645 return verify_expr(e
->param
[0]) &&
646 verify_expr(e
->param
[1]) &&
647 verify_expr(e
->param
[2]);
648 default: return verify_expr(e
->param
[0]) && verify_expr(e
->param
[1]) && !e
->param
[2];
652 int av_expr_parse(AVExpr
**expr
, const char *s
,
653 const char * const *const_names
,
654 const char * const *func1_names
, double (* const *funcs1
)(void *, double),
655 const char * const *func2_names
, double (* const *funcs2
)(void *, double, double),
656 int log_offset
, void *log_ctx
)
660 char *w
= av_malloc(strlen(s
) + 1);
666 return AVERROR(ENOMEM
);
669 if (!av_isspace(*s
++)) *wp
++ = s
[-1];
672 p
.class = &eval_class
;
675 p
.const_names
= const_names
;
677 p
.func1_names
= func1_names
;
679 p
.func2_names
= func2_names
;
680 p
.log_offset
= log_offset
;
683 if ((ret
= parse_expr(&e
, &p
)) < 0)
687 av_log(&p
, AV_LOG_ERROR
, "Invalid chars '%s' at the end of expression '%s'\n", p
.s
, s0
);
688 ret
= AVERROR(EINVAL
);
691 if (!verify_expr(e
)) {
693 ret
= AVERROR(EINVAL
);
696 e
->var
= av_mallocz(sizeof(double) *VARS
);
703 double av_expr_eval(AVExpr
*e
, const double *const_values
, void *opaque
)
708 p
.const_values
= const_values
;
710 return eval_expr(&p
, e
);
713 int av_expr_parse_and_eval(double *d
, const char *s
,
714 const char * const *const_names
, const double *const_values
,
715 const char * const *func1_names
, double (* const *funcs1
)(void *, double),
716 const char * const *func2_names
, double (* const *funcs2
)(void *, double, double),
717 void *opaque
, int log_offset
, void *log_ctx
)
720 int ret
= av_expr_parse(&e
, s
, const_names
, func1_names
, funcs1
, func2_names
, funcs2
, log_offset
, log_ctx
);
726 *d
= av_expr_eval(e
, const_values
, opaque
);
728 return isnan(*d
) ? AVERROR(EINVAL
) : 0;
734 static const double const_values
[] = {
740 static const char *const const_names
[] = {
746 int main(int argc
, char **argv
)
750 const char *const *expr
;
751 static const char *const exprs
[] = {
757 "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
778 "bar + PI + E + 100f*2 + foo",
779 "13k + 12f - foo(1, 2)",
792 /* compute 1+2+...+N */
793 "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)",
795 "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)",
797 "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))",
826 "ifnot(1, NaN) + if(0, 1)",
830 "taylor(eq(mod(ld(1),4),1)-eq(mod(ld(1),4),3), PI/2, 1)",
831 "root(sin(ld(0))-1, 2)",
832 "root(sin(ld(0))+6+sin(ld(0)/12)-log(ld(0)), 100)",
833 "7000000B*random(0)",
837 "gcd(30,55)*print(min(9,1))",
841 "between(10, -3, 10)",
842 "between(-4, -2, -1)",
850 for (expr
= exprs
; *expr
; expr
++) {
851 printf("Evaluating '%s'\n", *expr
);
852 av_expr_parse_and_eval(&d
, *expr
,
853 const_names
, const_values
,
854 NULL
, NULL
, NULL
, NULL
, NULL
, 0, NULL
);
856 printf("'%s' -> nan\n\n", *expr
);
858 printf("'%s' -> %f\n\n", *expr
, d
);
861 av_expr_parse_and_eval(&d
, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
862 const_names
, const_values
,
863 NULL
, NULL
, NULL
, NULL
, NULL
, 0, NULL
);
864 printf("%f == 12.7\n", d
);
865 av_expr_parse_and_eval(&d
, "80G/80Gi",
866 const_names
, const_values
,
867 NULL
, NULL
, NULL
, NULL
, NULL
, 0, NULL
);
868 printf("%f == 0.931322575\n", d
);
870 if (argc
> 1 && !strcmp(argv
[1], "-t")) {
871 for (i
= 0; i
< 1050; i
++) {
873 av_expr_parse_and_eval(&d
, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
874 const_names
, const_values
,
875 NULL
, NULL
, NULL
, NULL
, NULL
, 0, NULL
);
876 STOP_TIMER("av_expr_parse_and_eval");