Mercurial > libavcodec.hg
annotate eval.c @ 10061:09f2db2d7c90 libavcodec
Fix bug caused by difference in stride and picture width.
When a frame is allocated using libschroedinger routines, the frame data size
does not match the actual frame size if the width is not a multiple of 16. So
we cannot do a straightforward memcpy of the frame returned by libschroedinger
into the FFmpeg picture as the stride differs from the width.
Fix this bug by allocating for the libschroedinger frame with the dimensions
in AVCodecContext within libavcodec and passing the frame to libschroedinger.
patch by Anuradha Suraparaju, anuradha rd.bbc.co uk
| author | diego |
|---|---|
| date | Sat, 15 Aug 2009 11:59:53 +0000 |
| parents | 8f08abb1dffa |
| children | 685af2860d80 |
| 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 /** |
|
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8320
diff
changeset
|
25 * @file libavcodec/eval.c |
| 1106 | 26 * simple arithmetic expression evaluator. |
| 27 * | |
| 612 | 28 * see http://joe.hotchkiss.com/programming/eval/eval.html |
| 29 */ | |
| 30 | |
| 31 #include <stdio.h> | |
| 32 #include <stdlib.h> | |
| 33 #include <string.h> | |
| 34 #include <math.h> | |
| 35 | |
|
10040
8f08abb1dffa
eval: include libavutil/mathematics.h for NAN and M_PI
mru
parents:
10039
diff
changeset
|
36 #include "libavutil/mathematics.h" |
| 10039 | 37 #include "avcodec.h" |
| 38 #include "eval.h" | |
| 39 | |
| 612 | 40 typedef struct Parser{ |
| 41 int stack_index; | |
| 42 char *s; | |
| 8320 | 43 const double *const_value; |
| 44 const char * const *const_name; // NULL terminated | |
| 612 | 45 double (**func1)(void *, double a); // NULL terminated |
| 1057 | 46 const char **func1_name; // NULL terminated |
| 612 | 47 double (**func2)(void *, double a, double b); // NULL terminated |
| 8320 | 48 const char **func2_name; // NULL terminated |
| 612 | 49 void *opaque; |
| 6324 | 50 const char **error; |
| 4089 | 51 #define VARS 10 |
| 52 double var[VARS]; | |
| 612 | 53 } Parser; |
| 54 | |
| 7129 | 55 static const int8_t si_prefixes['z' - 'E' + 1]={ |
| 3778 | 56 ['y'-'E']= -24, |
| 57 ['z'-'E']= -21, | |
| 58 ['a'-'E']= -18, | |
| 59 ['f'-'E']= -15, | |
| 60 ['p'-'E']= -12, | |
| 61 ['n'-'E']= - 9, | |
| 62 ['u'-'E']= - 6, | |
| 63 ['m'-'E']= - 3, | |
| 64 ['c'-'E']= - 2, | |
| 65 ['d'-'E']= - 1, | |
| 66 ['h'-'E']= 2, | |
| 67 ['k'-'E']= 3, | |
| 68 ['K'-'E']= 3, | |
| 69 ['M'-'E']= 6, | |
| 70 ['G'-'E']= 9, | |
| 71 ['T'-'E']= 12, | |
| 72 ['P'-'E']= 15, | |
| 73 ['E'-'E']= 18, | |
| 74 ['Z'-'E']= 21, | |
| 75 ['Y'-'E']= 24, | |
| 76 }; | |
| 3756 | 77 |
| 9880 | 78 double av_strtod(const char *numstr, char **tail) { |
| 3778 | 79 double d; |
| 80 char *next; | |
|
9879
d54ba41c7e48
Cosmetics: rename 'name' av_strtod() param to 'numstr'. The new name
stefano
parents:
8718
diff
changeset
|
81 d = strtod(numstr, &next); |
| 3778 | 82 /* if parsing succeeded, check for and interpret postfixes */ |
|
9879
d54ba41c7e48
Cosmetics: rename 'name' av_strtod() param to 'numstr'. The new name
stefano
parents:
8718
diff
changeset
|
83 if (next!=numstr) { |
| 3778 | 84 |
| 85 if(*next >= 'E' && *next <= 'z'){ | |
| 86 int e= si_prefixes[*next - 'E']; | |
| 87 if(e){ | |
| 88 if(next[1] == 'i'){ | |
| 89 d*= pow( 2, e/0.3); | |
| 90 next+=2; | |
| 91 }else{ | |
| 92 d*= pow(10, e); | |
| 93 next++; | |
| 94 } | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 if(*next=='B') { | |
| 99 d*=8; | |
| 4355 | 100 next++; |
| 3778 | 101 } |
| 102 } | |
| 103 /* if requested, fill in tail with the position after the last parsed | |
| 104 character */ | |
| 105 if (tail) | |
| 106 *tail = next; | |
| 107 return d; | |
| 108 } | |
| 612 | 109 |
| 1057 | 110 static int strmatch(const char *s, const char *prefix){ |
| 612 | 111 int i; |
| 112 for(i=0; prefix[i]; i++){ | |
| 113 if(prefix[i] != s[i]) return 0; | |
| 114 } | |
| 115 return 1; | |
| 116 } | |
| 117 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
118 struct ff_expr_s { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
119 enum { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
120 e_value, e_const, e_func0, e_func1, e_func2, |
| 4089 | 121 e_squish, e_gauss, e_ld, |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
122 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
|
123 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
|
124 e_last, e_st, e_while, |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
125 } type; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
126 double value; // is sign in other types |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
127 union { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
128 int const_index; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
129 double (*func0)(double); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
130 double (*func1)(void *, double); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
131 double (*func2)(void *, double, double); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
132 } a; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
133 AVEvalExpr * param[2]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
134 }; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
135 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
136 static double eval_expr(Parser * p, AVEvalExpr * e) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
137 switch (e->type) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
138 case e_value: return e->value; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
139 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
|
140 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
|
141 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
|
142 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
|
143 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
|
144 case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); } |
| 4594 | 145 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
|
146 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
|
147 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
|
148 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
|
149 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
|
150 return d; |
|
8e35dfc4ae15
add support for while() loops again ugly syntax while(condition, statements) but very simple implementation
michael
parents:
4089
diff
changeset
|
151 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
152 default: { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
153 double d = eval_expr(p, e->param[0]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
154 double d2 = eval_expr(p, e->param[1]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
155 switch (e->type) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
156 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
|
157 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
|
158 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
|
159 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
|
160 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
|
161 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
|
162 case e_pow: return e->value * pow(d, d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
163 case e_mul: return e->value * (d * d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
164 case e_div: return e->value * (d / d2); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
165 case e_add: return e->value * (d + d2); |
| 4093 | 166 case e_last:return e->value * d2; |
| 4594 | 167 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
|
168 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
169 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
170 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
171 return NAN; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
172 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
173 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
174 static AVEvalExpr * parse_expr(Parser *p); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
175 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
176 void ff_eval_free(AVEvalExpr * e) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
177 if (!e) return; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
178 ff_eval_free(e->param[0]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
179 ff_eval_free(e->param[1]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
180 av_freep(&e); |
|
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 static AVEvalExpr * parse_primary(Parser *p) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
184 AVEvalExpr * d = av_mallocz(sizeof(AVEvalExpr)); |
| 612 | 185 char *next= p->s; |
| 186 int i; | |
| 187 | |
| 188 /* number */ | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
189 d->value = av_strtod(p->s, &next); |
| 612 | 190 if(next != p->s){ |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
191 d->type = e_value; |
| 612 | 192 p->s= next; |
| 2434 | 193 return d; |
| 612 | 194 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
195 d->value = 1; |
| 2967 | 196 |
| 612 | 197 /* named constants */ |
| 2433 | 198 for(i=0; p->const_name && p->const_name[i]; i++){ |
| 612 | 199 if(strmatch(p->s, p->const_name[i])){ |
| 200 p->s+= strlen(p->const_name[i]); | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
201 d->type = e_const; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
202 d->a.const_index = i; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
203 return d; |
| 612 | 204 } |
| 205 } | |
| 2967 | 206 |
| 612 | 207 p->s= strchr(p->s, '('); |
| 208 if(p->s==NULL){ | |
| 6840 | 209 *p->error = "undefined constant or missing ("; |
| 3754 | 210 p->s= next; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
211 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
212 return NULL; |
| 612 | 213 } |
| 214 p->s++; // "(" | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
215 if (*next == '(') { // special case do-nothing |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
216 av_freep(&d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
217 d = parse_expr(p); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
218 if(p->s[0] != ')'){ |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
219 *p->error = "missing )"; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
220 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
221 return NULL; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
222 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
223 p->s++; // ")" |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
224 return d; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
225 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
226 d->param[0] = parse_expr(p); |
| 1815 | 227 if(p->s[0]== ','){ |
| 228 p->s++; // "," | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
229 d->param[1] = parse_expr(p); |
| 612 | 230 } |
| 1815 | 231 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
|
232 *p->error = "missing )"; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
233 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
234 return NULL; |
| 1815 | 235 } |
| 236 p->s++; // ")" | |
| 2967 | 237 |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
238 d->type = e_func0; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
239 if( strmatch(next, "sinh" ) ) d->a.func0 = sinh; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
240 else if( strmatch(next, "cosh" ) ) d->a.func0 = cosh; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
241 else if( strmatch(next, "tanh" ) ) d->a.func0 = tanh; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
242 else if( strmatch(next, "sin" ) ) d->a.func0 = sin; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
243 else if( strmatch(next, "cos" ) ) d->a.func0 = cos; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
244 else if( strmatch(next, "tan" ) ) d->a.func0 = tan; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
245 else if( strmatch(next, "atan" ) ) d->a.func0 = atan; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
246 else if( strmatch(next, "asin" ) ) d->a.func0 = asin; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
247 else if( strmatch(next, "acos" ) ) d->a.func0 = acos; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
248 else if( strmatch(next, "exp" ) ) d->a.func0 = exp; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
249 else if( strmatch(next, "log" ) ) d->a.func0 = log; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
250 else if( strmatch(next, "abs" ) ) d->a.func0 = fabs; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
251 else if( strmatch(next, "squish") ) d->type = e_squish; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
252 else if( strmatch(next, "gauss" ) ) d->type = e_gauss; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
253 else if( strmatch(next, "mod" ) ) d->type = e_mod; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
254 else if( strmatch(next, "max" ) ) d->type = e_max; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
255 else if( strmatch(next, "min" ) ) d->type = e_min; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
256 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
|
257 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
|
258 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
|
259 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
|
260 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 | 261 else if( strmatch(next, "ld" ) ) d->type = e_ld; |
| 262 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
|
263 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
|
264 else { |
| 612 | 265 for(i=0; p->func1_name && p->func1_name[i]; i++){ |
| 266 if(strmatch(next, p->func1_name[i])){ | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
267 d->a.func1 = p->func1[i]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
268 d->type = e_func1; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
269 return d; |
| 612 | 270 } |
| 271 } | |
| 272 | |
| 273 for(i=0; p->func2_name && p->func2_name[i]; i++){ | |
| 274 if(strmatch(next, p->func2_name[i])){ | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
275 d->a.func2 = p->func2[i]; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
276 d->type = e_func2; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
277 return d; |
| 612 | 278 } |
| 279 } | |
| 280 | |
|
3770
ea345e1e440f
Introduce ff_eval2 which is equivalent to ff_eval but does not log anything.
takis
parents:
3756
diff
changeset
|
281 *p->error = "unknown function"; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
282 ff_eval_free(d); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
283 return NULL; |
| 612 | 284 } |
| 2433 | 285 |
| 2434 | 286 return d; |
| 2967 | 287 } |
| 2436 | 288 |
| 4085 | 289 static AVEvalExpr * new_eval_expr(int type, int value, AVEvalExpr *p0, AVEvalExpr *p1){ |
| 290 AVEvalExpr * e = av_mallocz(sizeof(AVEvalExpr)); | |
| 291 e->type =type ; | |
| 292 e->value =value ; | |
| 293 e->param[0] =p0 ; | |
| 294 e->param[1] =p1 ; | |
| 295 return e; | |
| 296 } | |
| 297 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
298 static AVEvalExpr * parse_pow(Parser *p, int *sign){ |
| 4032 | 299 *sign= (*p->s == '+') - (*p->s == '-'); |
| 300 p->s += *sign&1; | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
301 return parse_primary(p); |
| 2434 | 302 } |
| 612 | 303 |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
304 static AVEvalExpr * parse_factor(Parser *p){ |
| 4032 | 305 int sign, sign2; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
306 AVEvalExpr * e = parse_pow(p, &sign); |
| 2434 | 307 while(p->s[0]=='^'){ |
| 612 | 308 p->s++; |
| 4086 | 309 e= new_eval_expr(e_pow, 1, e, parse_pow(p, &sign2)); |
| 310 if (e->param[1]) e->param[1]->value *= (sign2|1); | |
| 612 | 311 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
312 if (e) e->value *= (sign|1); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
313 return e; |
| 612 | 314 } |
| 315 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
316 static AVEvalExpr * parse_term(Parser *p){ |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
317 AVEvalExpr * e = parse_factor(p); |
| 2434 | 318 while(p->s[0]=='*' || p->s[0]=='/'){ |
| 4085 | 319 int c= *p->s++; |
| 320 e= new_eval_expr(c == '*' ? e_mul : e_div, 1, e, parse_factor(p)); | |
| 612 | 321 } |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
322 return e; |
| 612 | 323 } |
| 324 | |
| 4089 | 325 static AVEvalExpr * parse_subexpr(Parser *p) { |
| 326 AVEvalExpr * e = parse_term(p); | |
| 327 while(*p->s == '+' || *p->s == '-') { | |
| 328 e= new_eval_expr(e_add, 1, e, parse_term(p)); | |
| 329 }; | |
| 330 | |
| 331 return e; | |
| 332 } | |
| 333 | |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
334 static AVEvalExpr * parse_expr(Parser *p) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
335 AVEvalExpr * e; |
| 612 | 336 |
| 2434 | 337 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
|
338 return NULL; |
| 2434 | 339 p->stack_index--; |
| 340 | |
| 4089 | 341 e = parse_subexpr(p); |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
342 |
| 4089 | 343 while(*p->s == ';') { |
| 344 p->s++; | |
| 345 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
|
346 }; |
| 612 | 347 |
| 2434 | 348 p->stack_index++; |
| 612 | 349 |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
350 return e; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
351 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
352 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
353 static int verify_expr(AVEvalExpr * e) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
354 if (!e) return 0; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
355 switch (e->type) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
356 case e_value: |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
357 case e_const: return 1; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
358 case e_func0: |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
359 case e_func1: |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
360 case e_squish: |
| 4089 | 361 case e_ld: |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
362 case e_gauss: return verify_expr(e->param[0]); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
363 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
|
364 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
365 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
366 |
| 8320 | 367 AVEvalExpr * ff_parse(const char *s, const char * const *const_name, |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
368 double (**func1)(void *, double), const char **func1_name, |
| 8320 | 369 double (**func2)(void *, double, double), const char **func2_name, |
| 6324 | 370 const char **error){ |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
371 Parser p; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
372 AVEvalExpr * e; |
| 4095 | 373 char w[strlen(s) + 1], * wp = w; |
| 374 | |
| 375 while (*s) | |
| 376 if (!isspace(*s++)) *wp++ = s[-1]; | |
| 377 *wp++ = 0; | |
|
4081
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 p.stack_index=100; |
| 4095 | 380 p.s= w; |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
381 p.const_name = const_name; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
382 p.func1 = func1; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
383 p.func1_name = func1_name; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
384 p.func2 = func2; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
385 p.func2_name = func2_name; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
386 p.error= error; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
387 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
388 e = parse_expr(&p); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
389 if (!verify_expr(e)) { |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
390 ff_eval_free(e); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
391 return NULL; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
392 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
393 return e; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
394 } |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
395 |
| 8320 | 396 double ff_parse_eval(AVEvalExpr * e, const double *const_value, void *opaque) { |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
397 Parser p; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
398 |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
399 p.const_value= const_value; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
400 p.opaque = opaque; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
401 return eval_expr(&p, e); |
| 612 | 402 } |
| 403 | |
| 8320 | 404 double ff_eval2(const char *s, const double *const_value, const char * const *const_name, |
| 1057 | 405 double (**func1)(void *, double), const char **func1_name, |
| 8320 | 406 double (**func2)(void *, double, double), const char **func2_name, |
| 6324 | 407 void *opaque, const char **error){ |
|
4081
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
408 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
|
409 double d; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
410 if (!e) return NAN; |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
411 d = ff_parse_eval(e, const_value, opaque); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
412 ff_eval_free(e); |
|
cedb63307f3d
new optimized eval method, by seperating parsing and runtime
ods15
parents:
4032
diff
changeset
|
413 return d; |
| 612 | 414 } |
| 2433 | 415 |
| 416 #ifdef TEST | |
| 2967 | 417 #undef printf |
| 2433 | 418 static double const_values[]={ |
| 419 M_PI, | |
| 420 M_E, | |
| 421 0 | |
| 422 }; | |
| 423 static const char *const_names[]={ | |
| 424 "PI", | |
| 425 "E", | |
| 426 0 | |
| 427 }; | |
| 6167 | 428 int main(void){ |
| 2436 | 429 int i; |
|
8108
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
430 printf("%f == 12.7\n", ff_eval2("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL)); |
|
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
431 printf("%f == 0.931322575\n", ff_eval2("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL)); |
| 2967 | 432 |
| 2436 | 433 for(i=0; i<1050; i++){ |
| 434 START_TIMER | |
|
8108
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
435 ff_eval2("1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)", const_values, const_names, NULL, NULL, NULL, NULL, NULL, NULL); |
|
5de6db4225d6
Fix test program build: ff_eval was replaced by ff_eval2.
diego
parents:
7824
diff
changeset
|
436 STOP_TIMER("ff_eval2") |
| 2436 | 437 } |
| 6167 | 438 return 0; |
| 2433 | 439 } |
| 440 #endif |
