Mercurial > libavcodec.hg
annotate eval.c @ 6323:e6da66f378c7 libavcodec
mpegvideo.h has two function declarations with the 'inline' specifier
but no definition for those functions. The C standard requires a
definition to appear in the same translation unit for any function
declared with 'inline'. Most of the files including mpegvideo.h do not
define those functions. Fix this by removing the 'inline' specifiers
from the header.
patch by Uoti Urpala
author | diego |
---|---|
date | Sun, 03 Feb 2008 17:54:30 +0000 |
parents | 0ae80d7e989a |
children | e378dca8784f |
rev | line source |
---|---|
612 | 1 /* |
2 * simple arithmetic expression evaluator | |
3 * | |
4101 | 4 * Copyright (c) 2002-2006 Michael Niedermayer <michaelni@gmx.at> |
4099
5e5c34470242
I hope noone minds, adding myself to eval.c copyright...
ods15
parents:
4095
diff
changeset
|
5 * Copyright (c) 2006 Oded Shimon <ods15@ods15.dyndns.org> |
612 | 6 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
7 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
8 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
9 * FFmpeg is free software; you can redistribute it and/or |
612 | 10 * modify it under the terms of the GNU Lesser General Public |
11 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
12 * version 2.1 of the License, or (at your option) any later version. |
612 | 13 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
14 * FFmpeg is distributed in the hope that it will be useful, |
612 | 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Lesser General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3920
diff
changeset
|
20 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2967
diff
changeset
|
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
612 | 22 */ |
23 | |
1106 | 24 /** |
25 * @file eval.c | |
26 * simple arithmetic expression evaluator. | |
27 * | |
612 | 28 * see http://joe.hotchkiss.com/programming/eval/eval.html |
29 */ | |
30 | |
1057 | 31 #include "avcodec.h" |
32 #include "mpegvideo.h" | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
33 #include "eval.h" |
1057 | 34 |
612 | 35 #include <stdio.h> |
36 #include <stdlib.h> | |
37 #include <string.h> | |
38 #include <math.h> | |
39 | |
614
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
40 #ifndef NAN |
3753 | 41 #define NAN 0.0/0.0 |
614
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
42 #endif |
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
43 |
627 | 44 #ifndef M_PI |
45 #define M_PI 3.14159265358979323846 | |
46 #endif | |
47 | |
612 | 48 typedef struct Parser{ |
49 int stack_index; | |
50 char *s; | |
51 double *const_value; | |
1057 | 52 const char **const_name; // NULL terminated |
612 | 53 double (**func1)(void *, double a); // NULL terminated |
1057 | 54 const char **func1_name; // NULL terminated |
612 | 55 double (**func2)(void *, double a, double b); // NULL terminated |
56 char **func2_name; // NULL terminated | |
57 void *opaque; | |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
58 char **error; |
4089 | 59 #define VARS 10 |
60 double var[VARS]; | |
612 | 61 } Parser; |
62 | |
3778 | 63 static int8_t si_prefixes['z' - 'E' + 1]={ |
64 ['y'-'E']= -24, | |
65 ['z'-'E']= -21, | |
66 ['a'-'E']= -18, | |
67 ['f'-'E']= -15, | |
68 ['p'-'E']= -12, | |
69 ['n'-'E']= - 9, | |
70 ['u'-'E']= - 6, | |
71 ['m'-'E']= - 3, | |
72 ['c'-'E']= - 2, | |
73 ['d'-'E']= - 1, | |
74 ['h'-'E']= 2, | |
75 ['k'-'E']= 3, | |
76 ['K'-'E']= 3, | |
77 ['M'-'E']= 6, | |
78 ['G'-'E']= 9, | |
79 ['T'-'E']= 12, | |
80 ['P'-'E']= 15, | |
81 ['E'-'E']= 18, | |
82 ['Z'-'E']= 21, | |
83 ['Y'-'E']= 24, | |
84 }; | |
3756 | 85 |
3778 | 86 /** strtod() function extended with 'k', 'M', 'G', 'ki', 'Mi', 'Gi' and 'B' |
87 * postfixes. This allows using f.e. kB, MiB, G and B as a postfix. This | |
88 * function assumes that the unit of numbers is bits not bytes. | |
89 */ | |
90 static double av_strtod(const char *name, char **tail) { | |
91 double d; | |
92 char *next; | |
93 d = strtod(name, &next); | |
94 /* if parsing succeeded, check for and interpret postfixes */ | |
95 if (next!=name) { | |
96 | |
97 if(*next >= 'E' && *next <= 'z'){ | |
98 int e= si_prefixes[*next - 'E']; | |
99 if(e){ | |
100 if(next[1] == 'i'){ | |
101 d*= pow( 2, e/0.3); | |
102 next+=2; | |
103 }else{ | |
104 d*= pow(10, e); | |
105 next++; | |
106 } | |
107 } | |
108 } | |
109 | |
110 if(*next=='B') { | |
111 d*=8; | |
4355 | 112 next++; |
3778 | 113 } |
114 } | |
115 /* if requested, fill in tail with the position after the last parsed | |
116 character */ | |
117 if (tail) | |
118 *tail = next; | |
119 return d; | |
120 } | |
612 | 121 |
1057 | 122 static int strmatch(const char *s, const char *prefix){ |
612 | 123 int i; |
124 for(i=0; prefix[i]; i++){ | |
125 if(prefix[i] != s[i]) return 0; | |
126 } | |
127 return 1; | |
128 } | |
129 | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
130 struct ff_expr_s { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
131 enum { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
132 e_value, e_const, e_func0, e_func1, e_func2, |
4089 | 133 e_squish, e_gauss, e_ld, |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
134 e_mod, e_max, e_min, e_eq, e_gt, e_gte, |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
135 e_pow, e_mul, e_div, e_add, |
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
136 e_last, e_st, e_while, |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
137 } type; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
138 double value; // is sign in other types |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
139 union { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
140 int const_index; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
141 double (*func0)(double); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
142 double (*func1)(void *, double); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
143 double (*func2)(void *, double, double); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
144 } a; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
145 AVEvalExpr * param[2]; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
146 }; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
147 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
148 static double eval_expr(Parser * p, AVEvalExpr * e) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
149 switch (e->type) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
150 case e_value: return e->value; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
151 case e_const: return e->value * p->const_value[e->a.const_index]; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
152 case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0])); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
153 case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0])); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
154 case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1])); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
155 case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0]))); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
156 case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); } |
4594 | 157 case e_ld: return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)]; |
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
158 case e_while: { |
4092
772ab2a1deaa
shut gcc warning, also makes sense for NAN to be returned if the loop was never executed
ods15
parents:
4090
diff
changeset
|
159 double d = NAN; |
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
160 while(eval_expr(p, e->param[0])) |
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
161 d=eval_expr(p, e->param[1]); |
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
162 return d; |
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
163 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
164 default: { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
165 double d = eval_expr(p, e->param[0]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
166 double d2 = eval_expr(p, e->param[1]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
167 switch (e->type) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
168 case e_mod: return e->value * (d - floor(d/d2)*d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
169 case e_max: return e->value * (d > d2 ? d : d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
170 case e_min: return e->value * (d < d2 ? d : d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
171 case e_eq: return e->value * (d == d2 ? 1.0 : 0.0); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
172 case e_gt: return e->value * (d > d2 ? 1.0 : 0.0); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
173 case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
174 case e_pow: return e->value * pow(d, d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
175 case e_mul: return e->value * (d * d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
176 case e_div: return e->value * (d / d2); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
177 case e_add: return e->value * (d + d2); |
4093 | 178 case e_last:return e->value * d2; |
4594 | 179 case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2); |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
180 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
181 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
182 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
183 return NAN; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
184 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
185 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
186 static AVEvalExpr * parse_expr(Parser *p); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
187 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
188 void ff_eval_free(AVEvalExpr * e) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
189 if (!e) return; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
190 ff_eval_free(e->param[0]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
191 ff_eval_free(e->param[1]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
192 av_freep(&e); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
193 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
194 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
195 static AVEvalExpr * parse_primary(Parser *p) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
196 AVEvalExpr * d = av_mallocz(sizeof(AVEvalExpr)); |
612 | 197 char *next= p->s; |
198 int i; | |
199 | |
200 /* number */ | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
201 d->value = av_strtod(p->s, &next); |
612 | 202 if(next != p->s){ |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
203 d->type = e_value; |
612 | 204 p->s= next; |
2434 | 205 return d; |
612 | 206 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
207 d->value = 1; |
2967 | 208 |
612 | 209 /* named constants */ |
2433 | 210 for(i=0; p->const_name && p->const_name[i]; i++){ |
612 | 211 if(strmatch(p->s, p->const_name[i])){ |
212 p->s+= strlen(p->const_name[i]); | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
213 d->type = e_const; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
214 d->a.const_index = i; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
215 return d; |
612 | 216 } |
217 } | |
2967 | 218 |
612 | 219 p->s= strchr(p->s, '('); |
220 if(p->s==NULL){ | |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
221 *p->error = "missing ("; |
3754 | 222 p->s= next; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
223 ff_eval_free(d); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
224 return NULL; |
612 | 225 } |
226 p->s++; // "(" | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
227 if (*next == '(') { // special case do-nothing |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
228 av_freep(&d); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
229 d = parse_expr(p); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
230 if(p->s[0] != ')'){ |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
231 *p->error = "missing )"; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
232 ff_eval_free(d); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
233 return NULL; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
234 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
235 p->s++; // ")" |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
236 return d; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
237 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
238 d->param[0] = parse_expr(p); |
1815 | 239 if(p->s[0]== ','){ |
240 p->s++; // "," | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
241 d->param[1] = parse_expr(p); |
612 | 242 } |
1815 | 243 if(p->s[0] != ')'){ |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
244 *p->error = "missing )"; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
245 ff_eval_free(d); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
246 return NULL; |
1815 | 247 } |
248 p->s++; // ")" | |
2967 | 249 |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
250 d->type = e_func0; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
251 if( strmatch(next, "sinh" ) ) d->a.func0 = sinh; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
252 else if( strmatch(next, "cosh" ) ) d->a.func0 = cosh; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
253 else if( strmatch(next, "tanh" ) ) d->a.func0 = tanh; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
254 else if( strmatch(next, "sin" ) ) d->a.func0 = sin; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
255 else if( strmatch(next, "cos" ) ) d->a.func0 = cos; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
256 else if( strmatch(next, "tan" ) ) d->a.func0 = tan; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
257 else if( strmatch(next, "atan" ) ) d->a.func0 = atan; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
258 else if( strmatch(next, "asin" ) ) d->a.func0 = asin; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
259 else if( strmatch(next, "acos" ) ) d->a.func0 = acos; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
260 else if( strmatch(next, "exp" ) ) d->a.func0 = exp; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
261 else if( strmatch(next, "log" ) ) d->a.func0 = log; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
262 else if( strmatch(next, "abs" ) ) d->a.func0 = fabs; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
263 else if( strmatch(next, "squish") ) d->type = e_squish; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
264 else if( strmatch(next, "gauss" ) ) d->type = e_gauss; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
265 else if( strmatch(next, "mod" ) ) d->type = e_mod; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
266 else if( strmatch(next, "max" ) ) d->type = e_max; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
267 else if( strmatch(next, "min" ) ) d->type = e_min; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
268 else if( strmatch(next, "eq" ) ) d->type = e_eq; |
4087
d4cdb9f6e888
possible bug of 'gte' being read as 'gt', same with 'lte'
ods15
parents:
4086
diff
changeset
|
269 else if( strmatch(next, "gte" ) ) d->type = e_gte; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
270 else if( strmatch(next, "gt" ) ) d->type = e_gt; |
4087
d4cdb9f6e888
possible bug of 'gte' being read as 'gt', same with 'lte'
ods15
parents:
4086
diff
changeset
|
271 else if( strmatch(next, "lte" ) ) { AVEvalExpr * tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
272 else if( strmatch(next, "lt" ) ) { AVEvalExpr * tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; } |
4089 | 273 else if( strmatch(next, "ld" ) ) d->type = e_ld; |
274 else if( strmatch(next, "st" ) ) d->type = e_st; | |
4090
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
275 else if( strmatch(next, "while" ) ) d->type = e_while; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
276 else { |
612 | 277 for(i=0; p->func1_name && p->func1_name[i]; i++){ |
278 if(strmatch(next, p->func1_name[i])){ | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
279 d->a.func1 = p->func1[i]; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
280 d->type = e_func1; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
281 return d; |
612 | 282 } |
283 } | |
284 | |
285 for(i=0; p->func2_name && p->func2_name[i]; i++){ | |
286 if(strmatch(next, p->func2_name[i])){ | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
287 d->a.func2 = p->func2[i]; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
288 d->type = e_func2; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
289 return d; |
612 | 290 } |
291 } | |
292 | |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
293 *p->error = "unknown function"; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
294 ff_eval_free(d); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
295 return NULL; |
612 | 296 } |
2433 | 297 |
2434 | 298 return d; |
2967 | 299 } |
2436 | 300 |
4085 | 301 static AVEvalExpr * new_eval_expr(int type, int value, AVEvalExpr *p0, AVEvalExpr *p1){ |
302 AVEvalExpr * e = av_mallocz(sizeof(AVEvalExpr)); | |
303 e->type =type ; | |
304 e->value =value ; | |
305 e->param[0] =p0 ; | |
306 e->param[1] =p1 ; | |
307 return e; | |
308 } | |
309 | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
310 static AVEvalExpr * parse_pow(Parser *p, int *sign){ |
4032 | 311 *sign= (*p->s == '+') - (*p->s == '-'); |
312 p->s += *sign&1; | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
313 return parse_primary(p); |
2434 | 314 } |
612 | 315 |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
316 static AVEvalExpr * parse_factor(Parser *p){ |
4032 | 317 int sign, sign2; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
318 AVEvalExpr * e = parse_pow(p, &sign); |
2434 | 319 while(p->s[0]=='^'){ |
612 | 320 p->s++; |
4086 | 321 e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2)); |
322 if (e->param[1]) e->param[1]->value *= (sign2|1); | |
612 | 323 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
324 if (e) e->value *= (sign|1); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
325 return e; |
612 | 326 } |
327 | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
328 static AVEvalExpr * parse_term(Parser *p){ |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
329 AVEvalExpr * e = parse_factor(p); |
2434 | 330 while(p->s[0]=='*' || p->s[0]=='/'){ |
4085 | 331 int c= *p->s++; |
332 e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p)); | |
612 | 333 } |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
334 return e; |
612 | 335 } |
336 | |
4089 | 337 static AVEvalExpr * parse_subexpr(Parser *p) { |
338 AVEvalExpr * e = parse_term(p); | |
339 while(*p->s == '+' || *p->s == '-') { | |
340 e= new_eval_expr(e_add, 1, e, parse_term(p)); | |
341 }; | |
342 | |
343 return e; | |
344 } | |
345 | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
346 static AVEvalExpr * parse_expr(Parser *p) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
347 AVEvalExpr * e; |
612 | 348 |
2434 | 349 if(p->stack_index <= 0) //protect against stack overflows |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
350 return NULL; |
2434 | 351 p->stack_index--; |
352 | |
4089 | 353 e = parse_subexpr(p); |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
354 |
4089 | 355 while(*p->s == ';') { |
356 p->s++; | |
357 e= new_eval_expr(e_last, 1, e, parse_subexpr(p)); | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
358 }; |
612 | 359 |
2434 | 360 p->stack_index++; |
612 | 361 |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
362 return e; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
363 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
364 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
365 static int verify_expr(AVEvalExpr * e) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
366 if (!e) return 0; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
367 switch (e->type) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
368 case e_value: |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
369 case e_const: return 1; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
370 case e_func0: |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
371 case e_func1: |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
372 case e_squish: |
4089 | 373 case e_ld: |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
374 case e_gauss: return verify_expr(e->param[0]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
375 default: return verify_expr(e->param[0]) && verify_expr(e->param[1]); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
376 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
377 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
378 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
379 AVEvalExpr * ff_parse(char *s, const char **const_name, |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
380 double (**func1)(void *, double), const char **func1_name, |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
381 double (**func2)(void *, double, double), char **func2_name, |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
382 char **error){ |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
383 Parser p; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
384 AVEvalExpr * e; |
4095 | 385 char w[strlen(s) + 1], * wp = w; |
386 | |
387 while (*s) | |
388 if (!isspace(*s++)) *wp++ = s[-1]; | |
389 *wp++ = 0; | |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
390 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
391 p.stack_index=100; |
4095 | 392 p.s= w; |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
393 p.const_name = const_name; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
394 p.func1 = func1; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
395 p.func1_name = func1_name; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
396 p.func2 = func2; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
397 p.func2_name = func2_name; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
398 p.error= error; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
399 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
400 e = parse_expr(&p); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
401 if (!verify_expr(e)) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
402 ff_eval_free(e); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
403 return NULL; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
404 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
405 return e; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
406 } |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
407 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
408 double ff_parse_eval(AVEvalExpr * e, double *const_value, void *opaque) { |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
409 Parser p; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
410 |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
411 p.const_value= const_value; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
412 p.opaque = opaque; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
413 return eval_expr(&p, e); |
612 | 414 } |
415 | |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
416 double ff_eval2(char *s, double *const_value, const char **const_name, |
1057 | 417 double (**func1)(void *, double), const char **func1_name, |
612 | 418 double (**func2)(void *, double, double), char **func2_name, |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
419 void *opaque, char **error){ |
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
420 AVEvalExpr * e = ff_parse(s, const_name, func1, func1_name, func2, func2_name, error); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
421 double d; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
422 if (!e) return NAN; |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
423 d = ff_parse_eval(e, const_value, opaque); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
424 ff_eval_free(e); |
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
425 return d; |
612 | 426 } |
2433 | 427 |
3779
3f7aa9fa5c98
Break compatibility only when first part of version number changes, in this
takis
parents:
3778
diff
changeset
|
428 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0) |
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
429 attribute_deprecated double ff_eval(char *s, double *const_value, const char **const_name, |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
430 double (**func1)(void *, double), const char **func1_name, |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
431 double (**func2)(void *, double, double), char **func2_name, |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
432 void *opaque){ |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
433 char *error=NULL; |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
434 double ret; |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
435 ret = ff_eval2(s, const_value, const_name, func1, func1_name, func2, func2_name, opaque, &error); |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
436 if (error) |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
437 av_log(NULL, AV_LOG_ERROR, "Error evaluating \"%s\": %s\n", s, error); |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
438 return ret; |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
439 } |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
440 #endif |
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
441 |
2433 | 442 #ifdef TEST |
2967 | 443 #undef printf |
2433 | 444 static double const_values[]={ |
445 M_PI, | |
446 M_E, | |
447 0 | |
448 }; | |
449 static const char *const_names[]={ | |
450 "PI", | |
451 "E", | |
452 0 | |
453 }; | |
6167 | 454 int main(void){ |
2436 | 455 int i; |
2433 | 456 printf("%f == 12.7\n", ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL)); |
3730 | 457 printf("%f == 0.931322575\n", ff_eval("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL)); |
2967 | 458 |
2436 | 459 for(i=0; i<1050; i++){ |
460 START_TIMER | |
461 ff_eval("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL); | |
462 STOP_TIMER("ff_eval") | |
463 } | |
6167 | 464 return 0; |
2433 | 465 } |
466 #endif |