e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round,
e_sqrt, e_not, e_random, e_hypot, e_gcd,
e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp,
+ e_sgn,
} type;
double value; // is sign in other types
+ int const_index;
union {
- int const_index;
double (*func0)(double);
double (*func1)(void *, double);
double (*func2)(void *, double, double);
{
switch (e->type) {
case e_value: return e->value;
- case e_const: return e->value * p->const_values[e->a.const_index];
+ case e_const: return e->value * p->const_values[e->const_index];
case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0]));
case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0]));
case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1]));
case e_ceil : return e->value * ceil (eval_expr(p, e->param[0]));
case e_trunc: return e->value * trunc(eval_expr(p, e->param[0]));
case e_round: return e->value * round(eval_expr(p, e->param[0]));
+ case e_sgn: return e->value * FFDIFFSIGN(eval_expr(p, e->param[0]), 0);
case e_sqrt: return e->value * sqrt (eval_expr(p, e->param[0]));
case e_not: return e->value * (eval_expr(p, e->param[0]) == 0);
case e_if: return e->value * (eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) :
double d = eval_expr(p, e->param[0]);
double d2 = eval_expr(p, e->param[1]);
switch (e->type) {
- case e_mod: return e->value * (d - floor((!CONFIG_FTRAPV || d2) ? d / d2 : d * INFINITY) * d2);
+ case e_mod: return e->value * (d - floor(d2 ? d / d2 : d * INFINITY) * d2);
case e_gcd: return e->value * av_gcd(d,d2);
case e_max: return e->value * (d > d2 ? d : d2);
case e_min: return e->value * (d < d2 ? d : d2);
case e_lte: return e->value * (d <= d2 ? 1.0 : 0.0);
case e_pow: return e->value * pow(d, d2);
case e_mul: return e->value * (d * d2);
- case e_div: return e->value * ((!CONFIG_FTRAPV || d2 ) ? (d / d2) : d * INFINITY);
+ case e_div: return e->value * (d2 ? (d / d2) : d * INFINITY);
case e_add: return e->value * (d + d2);
case e_last:return e->value * d2;
case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2);
if (strmatch(p->s, p->const_names[i])) {
p->s+= strlen(p->const_names[i]);
d->type = e_const;
- d->a.const_index = i;
+ d->const_index = i;
*e = d;
return 0;
}
else if (strmatch(next, "clip" )) d->type = e_clip;
else if (strmatch(next, "atan2" )) d->type = e_atan2;
else if (strmatch(next, "lerp" )) d->type = e_lerp;
+ else if (strmatch(next, "sgn" )) d->type = e_sgn;
else {
for (i=0; p->func1_names && p->func1_names[i]; i++) {
if (strmatch(next, p->func1_names[i])) {
d->a.func1 = p->funcs1[i];
d->type = e_func1;
+ d->const_index = i;
*e = d;
return 0;
}
if (strmatch(next, p->func2_names[i])) {
d->a.func2 = p->funcs2[i];
d->type = e_func2;
+ d->const_index = i;
*e = d;
return 0;
}
case e_sqrt:
case e_not:
case e_random:
+ case e_sgn:
return verify_expr(e->param[0]) && !e->param[1];
case e_print:
return verify_expr(e->param[0])
return ret;
}
+static int expr_count(AVExpr *e, unsigned *counter, int size, int type)
+{
+ int i;
+
+ if (!e || !counter || !size)
+ return AVERROR(EINVAL);
+
+ for (i = 0; e->type != type && i < 3 && e->param[i]; i++)
+ expr_count(e->param[i], counter, size, type);
+
+ if (e->type == type && e->const_index < size)
+ counter[e->const_index]++;
+
+ return 0;
+}
+
+int av_expr_count_vars(AVExpr *e, unsigned *counter, int size)
+{
+ return expr_count(e, counter, size, e_const);
+}
+
+int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg)
+{
+ return expr_count(e, counter, size, ((int[]){e_const, e_func1, e_func2})[arg]);
+}
+
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
{
Parser p = { 0 };