1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at>
3cabdff1aSopenharmony_ci * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org>
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * simple arithmetic expression evaluator.
25cabdff1aSopenharmony_ci *
26cabdff1aSopenharmony_ci * see http://joe.hotchkiss.com/programming/eval/eval.html
27cabdff1aSopenharmony_ci */
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include <float.h>
30cabdff1aSopenharmony_ci#include "attributes.h"
31cabdff1aSopenharmony_ci#include "avutil.h"
32cabdff1aSopenharmony_ci#include "common.h"
33cabdff1aSopenharmony_ci#include "eval.h"
34cabdff1aSopenharmony_ci#include "ffmath.h"
35cabdff1aSopenharmony_ci#include "internal.h"
36cabdff1aSopenharmony_ci#include "log.h"
37cabdff1aSopenharmony_ci#include "mathematics.h"
38cabdff1aSopenharmony_ci#include "time.h"
39cabdff1aSopenharmony_ci#include "avstring.h"
40cabdff1aSopenharmony_ci#include "timer.h"
41cabdff1aSopenharmony_ci#include "reverse.h"
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_citypedef struct Parser {
44cabdff1aSopenharmony_ci    const AVClass *class;
45cabdff1aSopenharmony_ci    int stack_index;
46cabdff1aSopenharmony_ci    char *s;
47cabdff1aSopenharmony_ci    const double *const_values;
48cabdff1aSopenharmony_ci    const char * const *const_names;          // NULL terminated
49cabdff1aSopenharmony_ci    double (* const *funcs1)(void *, double a);           // NULL terminated
50cabdff1aSopenharmony_ci    const char * const *func1_names;          // NULL terminated
51cabdff1aSopenharmony_ci    double (* const *funcs2)(void *, double a, double b); // NULL terminated
52cabdff1aSopenharmony_ci    const char * const *func2_names;          // NULL terminated
53cabdff1aSopenharmony_ci    void *opaque;
54cabdff1aSopenharmony_ci    int log_offset;
55cabdff1aSopenharmony_ci    void *log_ctx;
56cabdff1aSopenharmony_ci#define VARS 10
57cabdff1aSopenharmony_ci    double *var;
58cabdff1aSopenharmony_ci} Parser;
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_cistatic const AVClass eval_class = {
61cabdff1aSopenharmony_ci    .class_name                = "Eval",
62cabdff1aSopenharmony_ci    .item_name                 = av_default_item_name,
63cabdff1aSopenharmony_ci    .option                    = NULL,
64cabdff1aSopenharmony_ci    .version                   = LIBAVUTIL_VERSION_INT,
65cabdff1aSopenharmony_ci    .log_level_offset_offset   = offsetof(Parser, log_offset),
66cabdff1aSopenharmony_ci    .parent_log_context_offset = offsetof(Parser, log_ctx),
67cabdff1aSopenharmony_ci};
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_cistatic const struct {
70cabdff1aSopenharmony_ci    double bin_val;
71cabdff1aSopenharmony_ci    double dec_val;
72cabdff1aSopenharmony_ci    int8_t exp;
73cabdff1aSopenharmony_ci} si_prefixes['z' - 'E' + 1] = {
74cabdff1aSopenharmony_ci    ['y'-'E']= { 8.271806125530276749e-25, 1e-24, -24 },
75cabdff1aSopenharmony_ci    ['z'-'E']= { 8.4703294725430034e-22, 1e-21, -21 },
76cabdff1aSopenharmony_ci    ['a'-'E']= { 8.6736173798840355e-19, 1e-18, -18 },
77cabdff1aSopenharmony_ci    ['f'-'E']= { 8.8817841970012523e-16, 1e-15, -15 },
78cabdff1aSopenharmony_ci    ['p'-'E']= { 9.0949470177292824e-13, 1e-12, -12 },
79cabdff1aSopenharmony_ci    ['n'-'E']= { 9.3132257461547852e-10, 1e-9,  -9 },
80cabdff1aSopenharmony_ci    ['u'-'E']= { 9.5367431640625e-7, 1e-6, -6 },
81cabdff1aSopenharmony_ci    ['m'-'E']= { 9.765625e-4, 1e-3, -3 },
82cabdff1aSopenharmony_ci    ['c'-'E']= { 9.8431332023036951e-3, 1e-2, -2 },
83cabdff1aSopenharmony_ci    ['d'-'E']= { 9.921256574801246e-2, 1e-1, -1 },
84cabdff1aSopenharmony_ci    ['h'-'E']= { 1.0159366732596479e2, 1e2, 2 },
85cabdff1aSopenharmony_ci    ['k'-'E']= { 1.024e3, 1e3, 3 },
86cabdff1aSopenharmony_ci    ['K'-'E']= { 1.024e3, 1e3, 3 },
87cabdff1aSopenharmony_ci    ['M'-'E']= { 1.048576e6, 1e6, 6 },
88cabdff1aSopenharmony_ci    ['G'-'E']= { 1.073741824e9, 1e9, 9 },
89cabdff1aSopenharmony_ci    ['T'-'E']= { 1.099511627776e12, 1e12, 12 },
90cabdff1aSopenharmony_ci    ['P'-'E']= { 1.125899906842624e15, 1e15, 15 },
91cabdff1aSopenharmony_ci    ['E'-'E']= { 1.152921504606847e18, 1e18, 18 },
92cabdff1aSopenharmony_ci    ['Z'-'E']= { 1.1805916207174113e21, 1e21, 21 },
93cabdff1aSopenharmony_ci    ['Y'-'E']= { 1.2089258196146292e24, 1e24, 24 },
94cabdff1aSopenharmony_ci};
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_cistatic const struct {
97cabdff1aSopenharmony_ci    const char *name;
98cabdff1aSopenharmony_ci    double value;
99cabdff1aSopenharmony_ci} constants[] = {
100cabdff1aSopenharmony_ci    { "E",   M_E   },
101cabdff1aSopenharmony_ci    { "PI",  M_PI  },
102cabdff1aSopenharmony_ci    { "PHI", M_PHI },
103cabdff1aSopenharmony_ci    { "QP2LAMBDA", FF_QP2LAMBDA },
104cabdff1aSopenharmony_ci};
105cabdff1aSopenharmony_ci
106cabdff1aSopenharmony_cidouble av_strtod(const char *numstr, char **tail)
107cabdff1aSopenharmony_ci{
108cabdff1aSopenharmony_ci    double d;
109cabdff1aSopenharmony_ci    char *next;
110cabdff1aSopenharmony_ci    if(numstr[0]=='0' && (numstr[1]|0x20)=='x') {
111cabdff1aSopenharmony_ci        d = strtoul(numstr, &next, 16);
112cabdff1aSopenharmony_ci    } else
113cabdff1aSopenharmony_ci        d = strtod(numstr, &next);
114cabdff1aSopenharmony_ci    /* if parsing succeeded, check for and interpret postfixes */
115cabdff1aSopenharmony_ci    if (next!=numstr) {
116cabdff1aSopenharmony_ci        if (next[0] == 'd' && next[1] == 'B') {
117cabdff1aSopenharmony_ci            /* treat dB as decibels instead of decibytes */
118cabdff1aSopenharmony_ci            d = ff_exp10(d / 20);
119cabdff1aSopenharmony_ci            next += 2;
120cabdff1aSopenharmony_ci        } else if (*next >= 'E' && *next <= 'z') {
121cabdff1aSopenharmony_ci            int e= si_prefixes[*next - 'E'].exp;
122cabdff1aSopenharmony_ci            if (e) {
123cabdff1aSopenharmony_ci                if (next[1] == 'i') {
124cabdff1aSopenharmony_ci                    d*= si_prefixes[*next - 'E'].bin_val;
125cabdff1aSopenharmony_ci                    next+=2;
126cabdff1aSopenharmony_ci                } else {
127cabdff1aSopenharmony_ci                    d*= si_prefixes[*next - 'E'].dec_val;
128cabdff1aSopenharmony_ci                    next++;
129cabdff1aSopenharmony_ci                }
130cabdff1aSopenharmony_ci            }
131cabdff1aSopenharmony_ci        }
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci        if (*next=='B') {
134cabdff1aSopenharmony_ci            d*=8;
135cabdff1aSopenharmony_ci            next++;
136cabdff1aSopenharmony_ci        }
137cabdff1aSopenharmony_ci    }
138cabdff1aSopenharmony_ci    /* if requested, fill in tail with the position after the last parsed
139cabdff1aSopenharmony_ci       character */
140cabdff1aSopenharmony_ci    if (tail)
141cabdff1aSopenharmony_ci        *tail = next;
142cabdff1aSopenharmony_ci    return d;
143cabdff1aSopenharmony_ci}
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_ci#define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_')
146cabdff1aSopenharmony_ci
147cabdff1aSopenharmony_cistatic int strmatch(const char *s, const char *prefix)
148cabdff1aSopenharmony_ci{
149cabdff1aSopenharmony_ci    int i;
150cabdff1aSopenharmony_ci    for (i=0; prefix[i]; i++) {
151cabdff1aSopenharmony_ci        if (prefix[i] != s[i]) return 0;
152cabdff1aSopenharmony_ci    }
153cabdff1aSopenharmony_ci    /* return 1 only if the s identifier is terminated */
154cabdff1aSopenharmony_ci    return !IS_IDENTIFIER_CHAR(s[i]);
155cabdff1aSopenharmony_ci}
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_cistruct AVExpr {
158cabdff1aSopenharmony_ci    enum {
159cabdff1aSopenharmony_ci        e_value, e_const, e_func0, e_func1, e_func2,
160cabdff1aSopenharmony_ci        e_squish, e_gauss, e_ld, e_isnan, e_isinf,
161cabdff1aSopenharmony_ci        e_mod, e_max, e_min, e_eq, e_gt, e_gte, e_lte, e_lt,
162cabdff1aSopenharmony_ci        e_pow, e_mul, e_div, e_add,
163cabdff1aSopenharmony_ci        e_last, e_st, e_while, e_taylor, e_root, e_floor, e_ceil, e_trunc, e_round,
164cabdff1aSopenharmony_ci        e_sqrt, e_not, e_random, e_hypot, e_gcd,
165cabdff1aSopenharmony_ci        e_if, e_ifnot, e_print, e_bitand, e_bitor, e_between, e_clip, e_atan2, e_lerp,
166cabdff1aSopenharmony_ci        e_sgn,
167cabdff1aSopenharmony_ci    } type;
168cabdff1aSopenharmony_ci    double value; // is sign in other types
169cabdff1aSopenharmony_ci    int const_index;
170cabdff1aSopenharmony_ci    union {
171cabdff1aSopenharmony_ci        double (*func0)(double);
172cabdff1aSopenharmony_ci        double (*func1)(void *, double);
173cabdff1aSopenharmony_ci        double (*func2)(void *, double, double);
174cabdff1aSopenharmony_ci    } a;
175cabdff1aSopenharmony_ci    struct AVExpr *param[3];
176cabdff1aSopenharmony_ci    double *var;
177cabdff1aSopenharmony_ci};
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_cistatic double etime(double v)
180cabdff1aSopenharmony_ci{
181cabdff1aSopenharmony_ci    return av_gettime() * 0.000001;
182cabdff1aSopenharmony_ci}
183cabdff1aSopenharmony_ci
184cabdff1aSopenharmony_cistatic double eval_expr(Parser *p, AVExpr *e)
185cabdff1aSopenharmony_ci{
186cabdff1aSopenharmony_ci    switch (e->type) {
187cabdff1aSopenharmony_ci        case e_value:  return e->value;
188cabdff1aSopenharmony_ci        case e_const:  return e->value * p->const_values[e->const_index];
189cabdff1aSopenharmony_ci        case e_func0:  return e->value * e->a.func0(eval_expr(p, e->param[0]));
190cabdff1aSopenharmony_ci        case e_func1:  return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0]));
191cabdff1aSopenharmony_ci        case e_func2:  return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1]));
192cabdff1aSopenharmony_ci        case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0])));
193cabdff1aSopenharmony_ci        case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); }
194cabdff1aSopenharmony_ci        case e_ld:     return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)];
195cabdff1aSopenharmony_ci        case e_isnan:  return e->value * !!isnan(eval_expr(p, e->param[0]));
196cabdff1aSopenharmony_ci        case e_isinf:  return e->value * !!isinf(eval_expr(p, e->param[0]));
197cabdff1aSopenharmony_ci        case e_floor:  return e->value * floor(eval_expr(p, e->param[0]));
198cabdff1aSopenharmony_ci        case e_ceil :  return e->value * ceil (eval_expr(p, e->param[0]));
199cabdff1aSopenharmony_ci        case e_trunc:  return e->value * trunc(eval_expr(p, e->param[0]));
200cabdff1aSopenharmony_ci        case e_round:  return e->value * round(eval_expr(p, e->param[0]));
201cabdff1aSopenharmony_ci        case e_sgn:    return e->value * FFDIFFSIGN(eval_expr(p, e->param[0]), 0);
202cabdff1aSopenharmony_ci        case e_sqrt:   return e->value * sqrt (eval_expr(p, e->param[0]));
203cabdff1aSopenharmony_ci        case e_not:    return e->value * (eval_expr(p, e->param[0]) == 0);
204cabdff1aSopenharmony_ci        case e_if:     return e->value * (eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) :
205cabdff1aSopenharmony_ci                                          e->param[2] ? eval_expr(p, e->param[2]) : 0);
206cabdff1aSopenharmony_ci        case e_ifnot:  return e->value * (!eval_expr(p, e->param[0]) ? eval_expr(p, e->param[1]) :
207cabdff1aSopenharmony_ci                                          e->param[2] ? eval_expr(p, e->param[2]) : 0);
208cabdff1aSopenharmony_ci        case e_clip: {
209cabdff1aSopenharmony_ci            double x = eval_expr(p, e->param[0]);
210cabdff1aSopenharmony_ci            double min = eval_expr(p, e->param[1]), max = eval_expr(p, e->param[2]);
211cabdff1aSopenharmony_ci            if (isnan(min) || isnan(max) || isnan(x) || min > max)
212cabdff1aSopenharmony_ci                return NAN;
213cabdff1aSopenharmony_ci            return e->value * av_clipd(eval_expr(p, e->param[0]), min, max);
214cabdff1aSopenharmony_ci        }
215cabdff1aSopenharmony_ci        case e_between: {
216cabdff1aSopenharmony_ci            double d = eval_expr(p, e->param[0]);
217cabdff1aSopenharmony_ci            return e->value * (d >= eval_expr(p, e->param[1]) &&
218cabdff1aSopenharmony_ci                               d <= eval_expr(p, e->param[2]));
219cabdff1aSopenharmony_ci        }
220cabdff1aSopenharmony_ci        case e_lerp: {
221cabdff1aSopenharmony_ci            double v0 = eval_expr(p, e->param[0]);
222cabdff1aSopenharmony_ci            double v1 = eval_expr(p, e->param[1]);
223cabdff1aSopenharmony_ci            double f  = eval_expr(p, e->param[2]);
224cabdff1aSopenharmony_ci            return v0 + (v1 - v0) * f;
225cabdff1aSopenharmony_ci        }
226cabdff1aSopenharmony_ci        case e_print: {
227cabdff1aSopenharmony_ci            double x = eval_expr(p, e->param[0]);
228cabdff1aSopenharmony_ci            int level = e->param[1] ? av_clip(eval_expr(p, e->param[1]), INT_MIN, INT_MAX) : AV_LOG_INFO;
229cabdff1aSopenharmony_ci            av_log(p, level, "%f\n", x);
230cabdff1aSopenharmony_ci            return x;
231cabdff1aSopenharmony_ci        }
232cabdff1aSopenharmony_ci        case e_random:{
233cabdff1aSopenharmony_ci            int idx= av_clip(eval_expr(p, e->param[0]), 0, VARS-1);
234cabdff1aSopenharmony_ci            uint64_t r= isnan(p->var[idx]) ? 0 : p->var[idx];
235cabdff1aSopenharmony_ci            r= r*1664525+1013904223;
236cabdff1aSopenharmony_ci            p->var[idx]= r;
237cabdff1aSopenharmony_ci            return e->value * (r * (1.0/UINT64_MAX));
238cabdff1aSopenharmony_ci        }
239cabdff1aSopenharmony_ci        case e_while: {
240cabdff1aSopenharmony_ci            double d = NAN;
241cabdff1aSopenharmony_ci            while (eval_expr(p, e->param[0]))
242cabdff1aSopenharmony_ci                d=eval_expr(p, e->param[1]);
243cabdff1aSopenharmony_ci            return d;
244cabdff1aSopenharmony_ci        }
245cabdff1aSopenharmony_ci        case e_taylor: {
246cabdff1aSopenharmony_ci            double t = 1, d = 0, v;
247cabdff1aSopenharmony_ci            double x = eval_expr(p, e->param[1]);
248cabdff1aSopenharmony_ci            int id = e->param[2] ? av_clip(eval_expr(p, e->param[2]), 0, VARS-1) : 0;
249cabdff1aSopenharmony_ci            int i;
250cabdff1aSopenharmony_ci            double var0 = p->var[id];
251cabdff1aSopenharmony_ci            for(i=0; i<1000; i++) {
252cabdff1aSopenharmony_ci                double ld = d;
253cabdff1aSopenharmony_ci                p->var[id] = i;
254cabdff1aSopenharmony_ci                v = eval_expr(p, e->param[0]);
255cabdff1aSopenharmony_ci                d += t*v;
256cabdff1aSopenharmony_ci                if(ld==d && v)
257cabdff1aSopenharmony_ci                    break;
258cabdff1aSopenharmony_ci                t *= x / (i+1);
259cabdff1aSopenharmony_ci            }
260cabdff1aSopenharmony_ci            p->var[id] = var0;
261cabdff1aSopenharmony_ci            return d;
262cabdff1aSopenharmony_ci        }
263cabdff1aSopenharmony_ci        case e_root: {
264cabdff1aSopenharmony_ci            int i, j;
265cabdff1aSopenharmony_ci            double low = -1, high = -1, v, low_v = -DBL_MAX, high_v = DBL_MAX;
266cabdff1aSopenharmony_ci            double var0 = p->var[0];
267cabdff1aSopenharmony_ci            double x_max = eval_expr(p, e->param[1]);
268cabdff1aSopenharmony_ci            for(i=-1; i<1024; i++) {
269cabdff1aSopenharmony_ci                if(i<255) {
270cabdff1aSopenharmony_ci                    p->var[0] = ff_reverse[i&255]*x_max/255;
271cabdff1aSopenharmony_ci                } else {
272cabdff1aSopenharmony_ci                    p->var[0] = x_max*pow(0.9, i-255);
273cabdff1aSopenharmony_ci                    if (i&1) p->var[0] *= -1;
274cabdff1aSopenharmony_ci                    if (i&2) p->var[0] += low;
275cabdff1aSopenharmony_ci                    else     p->var[0] += high;
276cabdff1aSopenharmony_ci                }
277cabdff1aSopenharmony_ci                v = eval_expr(p, e->param[0]);
278cabdff1aSopenharmony_ci                if (v<=0 && v>low_v) {
279cabdff1aSopenharmony_ci                    low    = p->var[0];
280cabdff1aSopenharmony_ci                    low_v  = v;
281cabdff1aSopenharmony_ci                }
282cabdff1aSopenharmony_ci                if (v>=0 && v<high_v) {
283cabdff1aSopenharmony_ci                    high   = p->var[0];
284cabdff1aSopenharmony_ci                    high_v = v;
285cabdff1aSopenharmony_ci                }
286cabdff1aSopenharmony_ci                if (low>=0 && high>=0){
287cabdff1aSopenharmony_ci                    for (j=0; j<1000; j++) {
288cabdff1aSopenharmony_ci                        p->var[0] = (low+high)*0.5;
289cabdff1aSopenharmony_ci                        if (low == p->var[0] || high == p->var[0])
290cabdff1aSopenharmony_ci                            break;
291cabdff1aSopenharmony_ci                        v = eval_expr(p, e->param[0]);
292cabdff1aSopenharmony_ci                        if (v<=0) low = p->var[0];
293cabdff1aSopenharmony_ci                        if (v>=0) high= p->var[0];
294cabdff1aSopenharmony_ci                        if (isnan(v)) {
295cabdff1aSopenharmony_ci                            low = high = v;
296cabdff1aSopenharmony_ci                            break;
297cabdff1aSopenharmony_ci                        }
298cabdff1aSopenharmony_ci                    }
299cabdff1aSopenharmony_ci                    break;
300cabdff1aSopenharmony_ci                }
301cabdff1aSopenharmony_ci            }
302cabdff1aSopenharmony_ci            p->var[0] = var0;
303cabdff1aSopenharmony_ci            return -low_v<high_v ? low : high;
304cabdff1aSopenharmony_ci        }
305cabdff1aSopenharmony_ci        default: {
306cabdff1aSopenharmony_ci            double d = eval_expr(p, e->param[0]);
307cabdff1aSopenharmony_ci            double d2 = eval_expr(p, e->param[1]);
308cabdff1aSopenharmony_ci            switch (e->type) {
309cabdff1aSopenharmony_ci                case e_mod: return e->value * (d - floor(d2 ? d / d2 : d * INFINITY) * d2);
310cabdff1aSopenharmony_ci                case e_gcd: return e->value * av_gcd(d,d2);
311cabdff1aSopenharmony_ci                case e_max: return e->value * (d >  d2 ?   d : d2);
312cabdff1aSopenharmony_ci                case e_min: return e->value * (d <  d2 ?   d : d2);
313cabdff1aSopenharmony_ci                case e_eq:  return e->value * (d == d2 ? 1.0 : 0.0);
314cabdff1aSopenharmony_ci                case e_gt:  return e->value * (d >  d2 ? 1.0 : 0.0);
315cabdff1aSopenharmony_ci                case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0);
316cabdff1aSopenharmony_ci                case e_lt:  return e->value * (d <  d2 ? 1.0 : 0.0);
317cabdff1aSopenharmony_ci                case e_lte: return e->value * (d <= d2 ? 1.0 : 0.0);
318cabdff1aSopenharmony_ci                case e_pow: return e->value * pow(d, d2);
319cabdff1aSopenharmony_ci                case e_mul: return e->value * (d * d2);
320cabdff1aSopenharmony_ci                case e_div: return e->value * (d2 ? (d / d2) : d * INFINITY);
321cabdff1aSopenharmony_ci                case e_add: return e->value * (d + d2);
322cabdff1aSopenharmony_ci                case e_last:return e->value * d2;
323cabdff1aSopenharmony_ci                case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2);
324cabdff1aSopenharmony_ci                case e_hypot:return e->value * hypot(d, d2);
325cabdff1aSopenharmony_ci                case e_atan2:return e->value * atan2(d, d2);
326cabdff1aSopenharmony_ci                case e_bitand: return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d & (long int)d2);
327cabdff1aSopenharmony_ci                case e_bitor:  return isnan(d) || isnan(d2) ? NAN : e->value * ((long int)d | (long int)d2);
328cabdff1aSopenharmony_ci            }
329cabdff1aSopenharmony_ci        }
330cabdff1aSopenharmony_ci    }
331cabdff1aSopenharmony_ci    return NAN;
332cabdff1aSopenharmony_ci}
333cabdff1aSopenharmony_ci
334cabdff1aSopenharmony_cistatic int parse_expr(AVExpr **e, Parser *p);
335cabdff1aSopenharmony_ci
336cabdff1aSopenharmony_civoid av_expr_free(AVExpr *e)
337cabdff1aSopenharmony_ci{
338cabdff1aSopenharmony_ci    if (!e) return;
339cabdff1aSopenharmony_ci    av_expr_free(e->param[0]);
340cabdff1aSopenharmony_ci    av_expr_free(e->param[1]);
341cabdff1aSopenharmony_ci    av_expr_free(e->param[2]);
342cabdff1aSopenharmony_ci    av_freep(&e->var);
343cabdff1aSopenharmony_ci    av_freep(&e);
344cabdff1aSopenharmony_ci}
345cabdff1aSopenharmony_ci
346cabdff1aSopenharmony_cistatic int parse_primary(AVExpr **e, Parser *p)
347cabdff1aSopenharmony_ci{
348cabdff1aSopenharmony_ci    AVExpr *d = av_mallocz(sizeof(AVExpr));
349cabdff1aSopenharmony_ci    char *next = p->s, *s0 = p->s;
350cabdff1aSopenharmony_ci    int ret, i;
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci    if (!d)
353cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
354cabdff1aSopenharmony_ci
355cabdff1aSopenharmony_ci    /* number */
356cabdff1aSopenharmony_ci    d->value = av_strtod(p->s, &next);
357cabdff1aSopenharmony_ci    if (next != p->s) {
358cabdff1aSopenharmony_ci        d->type = e_value;
359cabdff1aSopenharmony_ci        p->s= next;
360cabdff1aSopenharmony_ci        *e = d;
361cabdff1aSopenharmony_ci        return 0;
362cabdff1aSopenharmony_ci    }
363cabdff1aSopenharmony_ci    d->value = 1;
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_ci    /* named constants */
366cabdff1aSopenharmony_ci    for (i=0; p->const_names && p->const_names[i]; i++) {
367cabdff1aSopenharmony_ci        if (strmatch(p->s, p->const_names[i])) {
368cabdff1aSopenharmony_ci            p->s+= strlen(p->const_names[i]);
369cabdff1aSopenharmony_ci            d->type = e_const;
370cabdff1aSopenharmony_ci            d->const_index = i;
371cabdff1aSopenharmony_ci            *e = d;
372cabdff1aSopenharmony_ci            return 0;
373cabdff1aSopenharmony_ci        }
374cabdff1aSopenharmony_ci    }
375cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(constants); i++) {
376cabdff1aSopenharmony_ci        if (strmatch(p->s, constants[i].name)) {
377cabdff1aSopenharmony_ci            p->s += strlen(constants[i].name);
378cabdff1aSopenharmony_ci            d->type = e_value;
379cabdff1aSopenharmony_ci            d->value = constants[i].value;
380cabdff1aSopenharmony_ci            *e = d;
381cabdff1aSopenharmony_ci            return 0;
382cabdff1aSopenharmony_ci        }
383cabdff1aSopenharmony_ci    }
384cabdff1aSopenharmony_ci
385cabdff1aSopenharmony_ci    p->s= strchr(p->s, '(');
386cabdff1aSopenharmony_ci    if (!p->s) {
387cabdff1aSopenharmony_ci        av_log(p, AV_LOG_ERROR, "Undefined constant or missing '(' in '%s'\n", s0);
388cabdff1aSopenharmony_ci        p->s= next;
389cabdff1aSopenharmony_ci        av_expr_free(d);
390cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
391cabdff1aSopenharmony_ci    }
392cabdff1aSopenharmony_ci    p->s++; // "("
393cabdff1aSopenharmony_ci    if (*next == '(') { // special case do-nothing
394cabdff1aSopenharmony_ci        av_freep(&d);
395cabdff1aSopenharmony_ci        if ((ret = parse_expr(&d, p)) < 0)
396cabdff1aSopenharmony_ci            return ret;
397cabdff1aSopenharmony_ci        if (p->s[0] != ')') {
398cabdff1aSopenharmony_ci            av_log(p, AV_LOG_ERROR, "Missing ')' in '%s'\n", s0);
399cabdff1aSopenharmony_ci            av_expr_free(d);
400cabdff1aSopenharmony_ci            return AVERROR(EINVAL);
401cabdff1aSopenharmony_ci        }
402cabdff1aSopenharmony_ci        p->s++; // ")"
403cabdff1aSopenharmony_ci        *e = d;
404cabdff1aSopenharmony_ci        return 0;
405cabdff1aSopenharmony_ci    }
406cabdff1aSopenharmony_ci    if ((ret = parse_expr(&(d->param[0]), p)) < 0) {
407cabdff1aSopenharmony_ci        av_expr_free(d);
408cabdff1aSopenharmony_ci        return ret;
409cabdff1aSopenharmony_ci    }
410cabdff1aSopenharmony_ci    if (p->s[0]== ',') {
411cabdff1aSopenharmony_ci        p->s++; // ","
412cabdff1aSopenharmony_ci        parse_expr(&d->param[1], p);
413cabdff1aSopenharmony_ci    }
414cabdff1aSopenharmony_ci    if (p->s[0]== ',') {
415cabdff1aSopenharmony_ci        p->s++; // ","
416cabdff1aSopenharmony_ci        parse_expr(&d->param[2], p);
417cabdff1aSopenharmony_ci    }
418cabdff1aSopenharmony_ci    if (p->s[0] != ')') {
419cabdff1aSopenharmony_ci        av_log(p, AV_LOG_ERROR, "Missing ')' or too many args in '%s'\n", s0);
420cabdff1aSopenharmony_ci        av_expr_free(d);
421cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
422cabdff1aSopenharmony_ci    }
423cabdff1aSopenharmony_ci    p->s++; // ")"
424cabdff1aSopenharmony_ci
425cabdff1aSopenharmony_ci    d->type = e_func0;
426cabdff1aSopenharmony_ci         if (strmatch(next, "sinh"  )) d->a.func0 = sinh;
427cabdff1aSopenharmony_ci    else if (strmatch(next, "cosh"  )) d->a.func0 = cosh;
428cabdff1aSopenharmony_ci    else if (strmatch(next, "tanh"  )) d->a.func0 = tanh;
429cabdff1aSopenharmony_ci    else if (strmatch(next, "sin"   )) d->a.func0 = sin;
430cabdff1aSopenharmony_ci    else if (strmatch(next, "cos"   )) d->a.func0 = cos;
431cabdff1aSopenharmony_ci    else if (strmatch(next, "tan"   )) d->a.func0 = tan;
432cabdff1aSopenharmony_ci    else if (strmatch(next, "atan"  )) d->a.func0 = atan;
433cabdff1aSopenharmony_ci    else if (strmatch(next, "asin"  )) d->a.func0 = asin;
434cabdff1aSopenharmony_ci    else if (strmatch(next, "acos"  )) d->a.func0 = acos;
435cabdff1aSopenharmony_ci    else if (strmatch(next, "exp"   )) d->a.func0 = exp;
436cabdff1aSopenharmony_ci    else if (strmatch(next, "log"   )) d->a.func0 = log;
437cabdff1aSopenharmony_ci    else if (strmatch(next, "abs"   )) d->a.func0 = fabs;
438cabdff1aSopenharmony_ci    else if (strmatch(next, "time"  )) d->a.func0 = etime;
439cabdff1aSopenharmony_ci    else if (strmatch(next, "squish")) d->type = e_squish;
440cabdff1aSopenharmony_ci    else if (strmatch(next, "gauss" )) d->type = e_gauss;
441cabdff1aSopenharmony_ci    else if (strmatch(next, "mod"   )) d->type = e_mod;
442cabdff1aSopenharmony_ci    else if (strmatch(next, "max"   )) d->type = e_max;
443cabdff1aSopenharmony_ci    else if (strmatch(next, "min"   )) d->type = e_min;
444cabdff1aSopenharmony_ci    else if (strmatch(next, "eq"    )) d->type = e_eq;
445cabdff1aSopenharmony_ci    else if (strmatch(next, "gte"   )) d->type = e_gte;
446cabdff1aSopenharmony_ci    else if (strmatch(next, "gt"    )) d->type = e_gt;
447cabdff1aSopenharmony_ci    else if (strmatch(next, "lte"   )) d->type = e_lte;
448cabdff1aSopenharmony_ci    else if (strmatch(next, "lt"    )) d->type = e_lt;
449cabdff1aSopenharmony_ci    else if (strmatch(next, "ld"    )) d->type = e_ld;
450cabdff1aSopenharmony_ci    else if (strmatch(next, "isnan" )) d->type = e_isnan;
451cabdff1aSopenharmony_ci    else if (strmatch(next, "isinf" )) d->type = e_isinf;
452cabdff1aSopenharmony_ci    else if (strmatch(next, "st"    )) d->type = e_st;
453cabdff1aSopenharmony_ci    else if (strmatch(next, "while" )) d->type = e_while;
454cabdff1aSopenharmony_ci    else if (strmatch(next, "taylor")) d->type = e_taylor;
455cabdff1aSopenharmony_ci    else if (strmatch(next, "root"  )) d->type = e_root;
456cabdff1aSopenharmony_ci    else if (strmatch(next, "floor" )) d->type = e_floor;
457cabdff1aSopenharmony_ci    else if (strmatch(next, "ceil"  )) d->type = e_ceil;
458cabdff1aSopenharmony_ci    else if (strmatch(next, "trunc" )) d->type = e_trunc;
459cabdff1aSopenharmony_ci    else if (strmatch(next, "round" )) d->type = e_round;
460cabdff1aSopenharmony_ci    else if (strmatch(next, "sqrt"  )) d->type = e_sqrt;
461cabdff1aSopenharmony_ci    else if (strmatch(next, "not"   )) d->type = e_not;
462cabdff1aSopenharmony_ci    else if (strmatch(next, "pow"   )) d->type = e_pow;
463cabdff1aSopenharmony_ci    else if (strmatch(next, "print" )) d->type = e_print;
464cabdff1aSopenharmony_ci    else if (strmatch(next, "random")) d->type = e_random;
465cabdff1aSopenharmony_ci    else if (strmatch(next, "hypot" )) d->type = e_hypot;
466cabdff1aSopenharmony_ci    else if (strmatch(next, "gcd"   )) d->type = e_gcd;
467cabdff1aSopenharmony_ci    else if (strmatch(next, "if"    )) d->type = e_if;
468cabdff1aSopenharmony_ci    else if (strmatch(next, "ifnot" )) d->type = e_ifnot;
469cabdff1aSopenharmony_ci    else if (strmatch(next, "bitand")) d->type = e_bitand;
470cabdff1aSopenharmony_ci    else if (strmatch(next, "bitor" )) d->type = e_bitor;
471cabdff1aSopenharmony_ci    else if (strmatch(next, "between"))d->type = e_between;
472cabdff1aSopenharmony_ci    else if (strmatch(next, "clip"  )) d->type = e_clip;
473cabdff1aSopenharmony_ci    else if (strmatch(next, "atan2" )) d->type = e_atan2;
474cabdff1aSopenharmony_ci    else if (strmatch(next, "lerp"  )) d->type = e_lerp;
475cabdff1aSopenharmony_ci    else if (strmatch(next, "sgn"   )) d->type = e_sgn;
476cabdff1aSopenharmony_ci    else {
477cabdff1aSopenharmony_ci        for (i=0; p->func1_names && p->func1_names[i]; i++) {
478cabdff1aSopenharmony_ci            if (strmatch(next, p->func1_names[i])) {
479cabdff1aSopenharmony_ci                d->a.func1 = p->funcs1[i];
480cabdff1aSopenharmony_ci                d->type = e_func1;
481cabdff1aSopenharmony_ci                d->const_index = i;
482cabdff1aSopenharmony_ci                *e = d;
483cabdff1aSopenharmony_ci                return 0;
484cabdff1aSopenharmony_ci            }
485cabdff1aSopenharmony_ci        }
486cabdff1aSopenharmony_ci
487cabdff1aSopenharmony_ci        for (i=0; p->func2_names && p->func2_names[i]; i++) {
488cabdff1aSopenharmony_ci            if (strmatch(next, p->func2_names[i])) {
489cabdff1aSopenharmony_ci                d->a.func2 = p->funcs2[i];
490cabdff1aSopenharmony_ci                d->type = e_func2;
491cabdff1aSopenharmony_ci                d->const_index = i;
492cabdff1aSopenharmony_ci                *e = d;
493cabdff1aSopenharmony_ci                return 0;
494cabdff1aSopenharmony_ci            }
495cabdff1aSopenharmony_ci        }
496cabdff1aSopenharmony_ci
497cabdff1aSopenharmony_ci        av_log(p, AV_LOG_ERROR, "Unknown function in '%s'\n", s0);
498cabdff1aSopenharmony_ci        av_expr_free(d);
499cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
500cabdff1aSopenharmony_ci    }
501cabdff1aSopenharmony_ci
502cabdff1aSopenharmony_ci    *e = d;
503cabdff1aSopenharmony_ci    return 0;
504cabdff1aSopenharmony_ci}
505cabdff1aSopenharmony_ci
506cabdff1aSopenharmony_cistatic AVExpr *make_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1)
507cabdff1aSopenharmony_ci{
508cabdff1aSopenharmony_ci    AVExpr *e = av_mallocz(sizeof(AVExpr));
509cabdff1aSopenharmony_ci    if (!e)
510cabdff1aSopenharmony_ci        return NULL;
511cabdff1aSopenharmony_ci    e->type     =type   ;
512cabdff1aSopenharmony_ci    e->value    =value  ;
513cabdff1aSopenharmony_ci    e->param[0] =p0     ;
514cabdff1aSopenharmony_ci    e->param[1] =p1     ;
515cabdff1aSopenharmony_ci    return e;
516cabdff1aSopenharmony_ci}
517cabdff1aSopenharmony_ci
518cabdff1aSopenharmony_cistatic int parse_pow(AVExpr **e, Parser *p, int *sign)
519cabdff1aSopenharmony_ci{
520cabdff1aSopenharmony_ci    *sign= (*p->s == '+') - (*p->s == '-');
521cabdff1aSopenharmony_ci    p->s += *sign&1;
522cabdff1aSopenharmony_ci    return parse_primary(e, p);
523cabdff1aSopenharmony_ci}
524cabdff1aSopenharmony_ci
525cabdff1aSopenharmony_cistatic int parse_dB(AVExpr **e, Parser *p, int *sign)
526cabdff1aSopenharmony_ci{
527cabdff1aSopenharmony_ci    /* do not filter out the negative sign when parsing a dB value.
528cabdff1aSopenharmony_ci       for example, -3dB is not the same as -(3dB) */
529cabdff1aSopenharmony_ci    if (*p->s == '-') {
530cabdff1aSopenharmony_ci        char *next;
531cabdff1aSopenharmony_ci        double av_unused ignored = strtod(p->s, &next);
532cabdff1aSopenharmony_ci        if (next != p->s && next[0] == 'd' && next[1] == 'B') {
533cabdff1aSopenharmony_ci            *sign = 0;
534cabdff1aSopenharmony_ci            return parse_primary(e, p);
535cabdff1aSopenharmony_ci        }
536cabdff1aSopenharmony_ci    }
537cabdff1aSopenharmony_ci    return parse_pow(e, p, sign);
538cabdff1aSopenharmony_ci}
539cabdff1aSopenharmony_ci
540cabdff1aSopenharmony_cistatic int parse_factor(AVExpr **e, Parser *p)
541cabdff1aSopenharmony_ci{
542cabdff1aSopenharmony_ci    int sign, sign2, ret;
543cabdff1aSopenharmony_ci    AVExpr *e0, *e1, *e2;
544cabdff1aSopenharmony_ci    if ((ret = parse_dB(&e0, p, &sign)) < 0)
545cabdff1aSopenharmony_ci        return ret;
546cabdff1aSopenharmony_ci    while(p->s[0]=='^'){
547cabdff1aSopenharmony_ci        e1 = e0;
548cabdff1aSopenharmony_ci        p->s++;
549cabdff1aSopenharmony_ci        if ((ret = parse_dB(&e2, p, &sign2)) < 0) {
550cabdff1aSopenharmony_ci            av_expr_free(e1);
551cabdff1aSopenharmony_ci            return ret;
552cabdff1aSopenharmony_ci        }
553cabdff1aSopenharmony_ci        e0 = make_eval_expr(e_pow, 1, e1, e2);
554cabdff1aSopenharmony_ci        if (!e0) {
555cabdff1aSopenharmony_ci            av_expr_free(e1);
556cabdff1aSopenharmony_ci            av_expr_free(e2);
557cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
558cabdff1aSopenharmony_ci        }
559cabdff1aSopenharmony_ci        if (e0->param[1]) e0->param[1]->value *= (sign2|1);
560cabdff1aSopenharmony_ci    }
561cabdff1aSopenharmony_ci    if (e0) e0->value *= (sign|1);
562cabdff1aSopenharmony_ci
563cabdff1aSopenharmony_ci    *e = e0;
564cabdff1aSopenharmony_ci    return 0;
565cabdff1aSopenharmony_ci}
566cabdff1aSopenharmony_ci
567cabdff1aSopenharmony_cistatic int parse_term(AVExpr **e, Parser *p)
568cabdff1aSopenharmony_ci{
569cabdff1aSopenharmony_ci    int ret;
570cabdff1aSopenharmony_ci    AVExpr *e0, *e1, *e2;
571cabdff1aSopenharmony_ci    if ((ret = parse_factor(&e0, p)) < 0)
572cabdff1aSopenharmony_ci        return ret;
573cabdff1aSopenharmony_ci    while (p->s[0]=='*' || p->s[0]=='/') {
574cabdff1aSopenharmony_ci        int c= *p->s++;
575cabdff1aSopenharmony_ci        e1 = e0;
576cabdff1aSopenharmony_ci        if ((ret = parse_factor(&e2, p)) < 0) {
577cabdff1aSopenharmony_ci            av_expr_free(e1);
578cabdff1aSopenharmony_ci            return ret;
579cabdff1aSopenharmony_ci        }
580cabdff1aSopenharmony_ci        e0 = make_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2);
581cabdff1aSopenharmony_ci        if (!e0) {
582cabdff1aSopenharmony_ci            av_expr_free(e1);
583cabdff1aSopenharmony_ci            av_expr_free(e2);
584cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
585cabdff1aSopenharmony_ci        }
586cabdff1aSopenharmony_ci    }
587cabdff1aSopenharmony_ci    *e = e0;
588cabdff1aSopenharmony_ci    return 0;
589cabdff1aSopenharmony_ci}
590cabdff1aSopenharmony_ci
591cabdff1aSopenharmony_cistatic int parse_subexpr(AVExpr **e, Parser *p)
592cabdff1aSopenharmony_ci{
593cabdff1aSopenharmony_ci    int ret;
594cabdff1aSopenharmony_ci    AVExpr *e0, *e1, *e2;
595cabdff1aSopenharmony_ci    if ((ret = parse_term(&e0, p)) < 0)
596cabdff1aSopenharmony_ci        return ret;
597cabdff1aSopenharmony_ci    while (*p->s == '+' || *p->s == '-') {
598cabdff1aSopenharmony_ci        e1 = e0;
599cabdff1aSopenharmony_ci        if ((ret = parse_term(&e2, p)) < 0) {
600cabdff1aSopenharmony_ci            av_expr_free(e1);
601cabdff1aSopenharmony_ci            return ret;
602cabdff1aSopenharmony_ci        }
603cabdff1aSopenharmony_ci        e0 = make_eval_expr(e_add, 1, e1, e2);
604cabdff1aSopenharmony_ci        if (!e0) {
605cabdff1aSopenharmony_ci            av_expr_free(e1);
606cabdff1aSopenharmony_ci            av_expr_free(e2);
607cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
608cabdff1aSopenharmony_ci        }
609cabdff1aSopenharmony_ci    };
610cabdff1aSopenharmony_ci
611cabdff1aSopenharmony_ci    *e = e0;
612cabdff1aSopenharmony_ci    return 0;
613cabdff1aSopenharmony_ci}
614cabdff1aSopenharmony_ci
615cabdff1aSopenharmony_cistatic int parse_expr(AVExpr **e, Parser *p)
616cabdff1aSopenharmony_ci{
617cabdff1aSopenharmony_ci    int ret;
618cabdff1aSopenharmony_ci    AVExpr *e0, *e1, *e2;
619cabdff1aSopenharmony_ci    if (p->stack_index <= 0) //protect against stack overflows
620cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
621cabdff1aSopenharmony_ci    p->stack_index--;
622cabdff1aSopenharmony_ci
623cabdff1aSopenharmony_ci    if ((ret = parse_subexpr(&e0, p)) < 0)
624cabdff1aSopenharmony_ci        return ret;
625cabdff1aSopenharmony_ci    while (*p->s == ';') {
626cabdff1aSopenharmony_ci        p->s++;
627cabdff1aSopenharmony_ci        e1 = e0;
628cabdff1aSopenharmony_ci        if ((ret = parse_subexpr(&e2, p)) < 0) {
629cabdff1aSopenharmony_ci            av_expr_free(e1);
630cabdff1aSopenharmony_ci            return ret;
631cabdff1aSopenharmony_ci        }
632cabdff1aSopenharmony_ci        e0 = make_eval_expr(e_last, 1, e1, e2);
633cabdff1aSopenharmony_ci        if (!e0) {
634cabdff1aSopenharmony_ci            av_expr_free(e1);
635cabdff1aSopenharmony_ci            av_expr_free(e2);
636cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
637cabdff1aSopenharmony_ci        }
638cabdff1aSopenharmony_ci    };
639cabdff1aSopenharmony_ci
640cabdff1aSopenharmony_ci    p->stack_index++;
641cabdff1aSopenharmony_ci    *e = e0;
642cabdff1aSopenharmony_ci    return 0;
643cabdff1aSopenharmony_ci}
644cabdff1aSopenharmony_ci
645cabdff1aSopenharmony_cistatic int verify_expr(AVExpr *e)
646cabdff1aSopenharmony_ci{
647cabdff1aSopenharmony_ci    if (!e) return 0;
648cabdff1aSopenharmony_ci    switch (e->type) {
649cabdff1aSopenharmony_ci        case e_value:
650cabdff1aSopenharmony_ci        case e_const: return 1;
651cabdff1aSopenharmony_ci        case e_func0:
652cabdff1aSopenharmony_ci        case e_func1:
653cabdff1aSopenharmony_ci        case e_squish:
654cabdff1aSopenharmony_ci        case e_ld:
655cabdff1aSopenharmony_ci        case e_gauss:
656cabdff1aSopenharmony_ci        case e_isnan:
657cabdff1aSopenharmony_ci        case e_isinf:
658cabdff1aSopenharmony_ci        case e_floor:
659cabdff1aSopenharmony_ci        case e_ceil:
660cabdff1aSopenharmony_ci        case e_trunc:
661cabdff1aSopenharmony_ci        case e_round:
662cabdff1aSopenharmony_ci        case e_sqrt:
663cabdff1aSopenharmony_ci        case e_not:
664cabdff1aSopenharmony_ci        case e_random:
665cabdff1aSopenharmony_ci        case e_sgn:
666cabdff1aSopenharmony_ci            return verify_expr(e->param[0]) && !e->param[1];
667cabdff1aSopenharmony_ci        case e_print:
668cabdff1aSopenharmony_ci            return verify_expr(e->param[0])
669cabdff1aSopenharmony_ci                   && (!e->param[1] || verify_expr(e->param[1]));
670cabdff1aSopenharmony_ci        case e_if:
671cabdff1aSopenharmony_ci        case e_ifnot:
672cabdff1aSopenharmony_ci        case e_taylor:
673cabdff1aSopenharmony_ci            return verify_expr(e->param[0]) && verify_expr(e->param[1])
674cabdff1aSopenharmony_ci                   && (!e->param[2] || verify_expr(e->param[2]));
675cabdff1aSopenharmony_ci        case e_between:
676cabdff1aSopenharmony_ci        case e_clip:
677cabdff1aSopenharmony_ci        case e_lerp:
678cabdff1aSopenharmony_ci            return verify_expr(e->param[0]) &&
679cabdff1aSopenharmony_ci                   verify_expr(e->param[1]) &&
680cabdff1aSopenharmony_ci                   verify_expr(e->param[2]);
681cabdff1aSopenharmony_ci        default: return verify_expr(e->param[0]) && verify_expr(e->param[1]) && !e->param[2];
682cabdff1aSopenharmony_ci    }
683cabdff1aSopenharmony_ci}
684cabdff1aSopenharmony_ci
685cabdff1aSopenharmony_ciint av_expr_parse(AVExpr **expr, const char *s,
686cabdff1aSopenharmony_ci                  const char * const *const_names,
687cabdff1aSopenharmony_ci                  const char * const *func1_names, double (* const *funcs1)(void *, double),
688cabdff1aSopenharmony_ci                  const char * const *func2_names, double (* const *funcs2)(void *, double, double),
689cabdff1aSopenharmony_ci                  int log_offset, void *log_ctx)
690cabdff1aSopenharmony_ci{
691cabdff1aSopenharmony_ci    Parser p = { 0 };
692cabdff1aSopenharmony_ci    AVExpr *e = NULL;
693cabdff1aSopenharmony_ci    char *w = av_malloc(strlen(s) + 1);
694cabdff1aSopenharmony_ci    char *wp = w;
695cabdff1aSopenharmony_ci    const char *s0 = s;
696cabdff1aSopenharmony_ci    int ret = 0;
697cabdff1aSopenharmony_ci
698cabdff1aSopenharmony_ci    if (!w)
699cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
700cabdff1aSopenharmony_ci
701cabdff1aSopenharmony_ci    while (*s)
702cabdff1aSopenharmony_ci        if (!av_isspace(*s++)) *wp++ = s[-1];
703cabdff1aSopenharmony_ci    *wp++ = 0;
704cabdff1aSopenharmony_ci
705cabdff1aSopenharmony_ci    p.class      = &eval_class;
706cabdff1aSopenharmony_ci    p.stack_index=100;
707cabdff1aSopenharmony_ci    p.s= w;
708cabdff1aSopenharmony_ci    p.const_names = const_names;
709cabdff1aSopenharmony_ci    p.funcs1      = funcs1;
710cabdff1aSopenharmony_ci    p.func1_names = func1_names;
711cabdff1aSopenharmony_ci    p.funcs2      = funcs2;
712cabdff1aSopenharmony_ci    p.func2_names = func2_names;
713cabdff1aSopenharmony_ci    p.log_offset = log_offset;
714cabdff1aSopenharmony_ci    p.log_ctx    = log_ctx;
715cabdff1aSopenharmony_ci
716cabdff1aSopenharmony_ci    if ((ret = parse_expr(&e, &p)) < 0)
717cabdff1aSopenharmony_ci        goto end;
718cabdff1aSopenharmony_ci    if (*p.s) {
719cabdff1aSopenharmony_ci        av_log(&p, AV_LOG_ERROR, "Invalid chars '%s' at the end of expression '%s'\n", p.s, s0);
720cabdff1aSopenharmony_ci        ret = AVERROR(EINVAL);
721cabdff1aSopenharmony_ci        goto end;
722cabdff1aSopenharmony_ci    }
723cabdff1aSopenharmony_ci    if (!verify_expr(e)) {
724cabdff1aSopenharmony_ci        ret = AVERROR(EINVAL);
725cabdff1aSopenharmony_ci        goto end;
726cabdff1aSopenharmony_ci    }
727cabdff1aSopenharmony_ci    e->var= av_mallocz(sizeof(double) *VARS);
728cabdff1aSopenharmony_ci    if (!e->var) {
729cabdff1aSopenharmony_ci        ret = AVERROR(ENOMEM);
730cabdff1aSopenharmony_ci        goto end;
731cabdff1aSopenharmony_ci    }
732cabdff1aSopenharmony_ci    *expr = e;
733cabdff1aSopenharmony_ci    e = NULL;
734cabdff1aSopenharmony_ciend:
735cabdff1aSopenharmony_ci    av_expr_free(e);
736cabdff1aSopenharmony_ci    av_free(w);
737cabdff1aSopenharmony_ci    return ret;
738cabdff1aSopenharmony_ci}
739cabdff1aSopenharmony_ci
740cabdff1aSopenharmony_cistatic int expr_count(AVExpr *e, unsigned *counter, int size, int type)
741cabdff1aSopenharmony_ci{
742cabdff1aSopenharmony_ci    int i;
743cabdff1aSopenharmony_ci
744cabdff1aSopenharmony_ci    if (!e || !counter || !size)
745cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
746cabdff1aSopenharmony_ci
747cabdff1aSopenharmony_ci    for (i = 0; e->type != type && i < 3 && e->param[i]; i++)
748cabdff1aSopenharmony_ci        expr_count(e->param[i], counter, size, type);
749cabdff1aSopenharmony_ci
750cabdff1aSopenharmony_ci    if (e->type == type && e->const_index < size)
751cabdff1aSopenharmony_ci        counter[e->const_index]++;
752cabdff1aSopenharmony_ci
753cabdff1aSopenharmony_ci    return 0;
754cabdff1aSopenharmony_ci}
755cabdff1aSopenharmony_ci
756cabdff1aSopenharmony_ciint av_expr_count_vars(AVExpr *e, unsigned *counter, int size)
757cabdff1aSopenharmony_ci{
758cabdff1aSopenharmony_ci    return expr_count(e, counter, size, e_const);
759cabdff1aSopenharmony_ci}
760cabdff1aSopenharmony_ci
761cabdff1aSopenharmony_ciint av_expr_count_func(AVExpr *e, unsigned *counter, int size, int arg)
762cabdff1aSopenharmony_ci{
763cabdff1aSopenharmony_ci    return expr_count(e, counter, size, ((int[]){e_const, e_func1, e_func2})[arg]);
764cabdff1aSopenharmony_ci}
765cabdff1aSopenharmony_ci
766cabdff1aSopenharmony_cidouble av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
767cabdff1aSopenharmony_ci{
768cabdff1aSopenharmony_ci    Parser p = { 0 };
769cabdff1aSopenharmony_ci    p.var= e->var;
770cabdff1aSopenharmony_ci
771cabdff1aSopenharmony_ci    p.const_values = const_values;
772cabdff1aSopenharmony_ci    p.opaque     = opaque;
773cabdff1aSopenharmony_ci    return eval_expr(&p, e);
774cabdff1aSopenharmony_ci}
775cabdff1aSopenharmony_ci
776cabdff1aSopenharmony_ciint av_expr_parse_and_eval(double *d, const char *s,
777cabdff1aSopenharmony_ci                           const char * const *const_names, const double *const_values,
778cabdff1aSopenharmony_ci                           const char * const *func1_names, double (* const *funcs1)(void *, double),
779cabdff1aSopenharmony_ci                           const char * const *func2_names, double (* const *funcs2)(void *, double, double),
780cabdff1aSopenharmony_ci                           void *opaque, int log_offset, void *log_ctx)
781cabdff1aSopenharmony_ci{
782cabdff1aSopenharmony_ci    AVExpr *e = NULL;
783cabdff1aSopenharmony_ci    int ret = av_expr_parse(&e, s, const_names, func1_names, funcs1, func2_names, funcs2, log_offset, log_ctx);
784cabdff1aSopenharmony_ci
785cabdff1aSopenharmony_ci    if (ret < 0) {
786cabdff1aSopenharmony_ci        *d = NAN;
787cabdff1aSopenharmony_ci        return ret;
788cabdff1aSopenharmony_ci    }
789cabdff1aSopenharmony_ci    *d = av_expr_eval(e, const_values, opaque);
790cabdff1aSopenharmony_ci    av_expr_free(e);
791cabdff1aSopenharmony_ci    return isnan(*d) ? AVERROR(EINVAL) : 0;
792cabdff1aSopenharmony_ci}
793