avutil/eval: Store *prng_state / var only in root AVExpr

AFter this, depth and the root element flag is stored in space
needed for alignment and thus does not increase the AVExpr size

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Michael Niedermayer
2026-02-26 17:39:24 +01:00
parent 1528ccb6a1
commit 5554d9d555

View File

@@ -28,6 +28,7 @@
#include <float.h> #include <float.h>
#include "attributes.h" #include "attributes.h"
#include "avassert.h"
#include "avutil.h" #include "avutil.h"
#include "common.h" #include "common.h"
#include "eval.h" #include "eval.h"
@@ -157,29 +158,35 @@ static int strmatch(const char *s, const char *prefix)
return !IS_IDENTIFIER_CHAR(s[i]); return !IS_IDENTIFIER_CHAR(s[i]);
} }
enum {
e_value, e_const, e_func0, e_func1, e_func2,
e_squish, e_gauss, e_ld, e_isnan, e_isinf,
e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt,
e_pow, e_mul, e_div, e_add,
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, e_randomi
};
struct AVExpr { struct AVExpr {
enum { unsigned char type;
e_value, e_const, e_func0, e_func1, e_func2, unsigned char root;
e_squish, e_gauss, e_ld, e_isnan, e_isinf, short depth;
e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt,
e_pow, e_mul, e_div, e_add,
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, e_randomi
} type;
double value; // is sign in other types
int const_index; int const_index;
double value; // is sign in other types
union { union {
double (*func0)(double); double (*func0)(double);
double (*func1)(void *, double); double (*func1)(void *, double);
double (*func2)(void *, double, double); double (*func2)(void *, double, double);
} ; } ;
struct AVExpr *param[3]; struct AVExpr *param[3];
};
typedef struct {
AVExpr avexpr;
double *var; double *var;
FFSFC64 *prng_state; FFSFC64 *prng_state;
int depth; } AVExprRoot;
};
static double etime(double v) static double etime(double v)
{ {
@@ -364,8 +371,11 @@ void av_expr_free(AVExpr *e)
av_expr_free(e->param[0]); av_expr_free(e->param[0]);
av_expr_free(e->param[1]); av_expr_free(e->param[1]);
av_expr_free(e->param[2]); av_expr_free(e->param[2]);
av_freep(&e->var); if (e->root) {
av_freep(&e->prng_state); AVExprRoot *r = (AVExprRoot*)e;
av_freep(&r->var);
av_freep(&r->prng_state);
}
av_freep(&e); av_freep(&e);
} }
@@ -764,9 +774,16 @@ int av_expr_parse(AVExpr **expr, const char *s,
ret = AVERROR(EINVAL); ret = AVERROR(EINVAL);
goto end; goto end;
} }
e->var= av_mallocz(sizeof(double) *VARS); AVExprRoot *r = av_realloc(e, sizeof(*r));
e->prng_state = av_mallocz(sizeof(*e->prng_state) *VARS); if (!r) {
if (!e->var || !e->prng_state) { ret = AVERROR(ENOMEM);
goto end;
}
e = (AVExpr*)r;
e->root = 1;
r->var= av_mallocz(sizeof(double) *VARS);
r->prng_state = av_mallocz(sizeof(*r->prng_state) *VARS);
if (!r->var || !r->prng_state) {
ret = AVERROR(ENOMEM); ret = AVERROR(ENOMEM);
goto end; goto end;
} }
@@ -806,12 +823,14 @@ int av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg)
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque) double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
{ {
av_assert1(e->root);
AVExprRoot *r = (AVExprRoot *)e;
Parser p = { Parser p = {
.class = &eval_class, .class = &eval_class,
.const_values = const_values, .const_values = const_values,
.opaque = opaque, .opaque = opaque,
.var = e->var, .var = r->var,
.prng_state = e->prng_state, .prng_state = r->prng_state,
}; };
return eval_expr(&p, e); return eval_expr(&p, e);