Mercurial > libavcodec.hg
annotate eval.c @ 2497:69adfbbdcdeb libavcodec
- samples from mplayer ftp in the "adv" profile seem to have profile=2,
which isn't the advanced one; and indeed, using adv. profile parser fails.
Using normal parser works, and that's what is done
- attempt at taking care of stride for NORM2 bitplane decoding
- duplication of much code from msmpeg4.c; this code isn't yet used, but
goes down as far as the block layer (mainly Transform Type stuff, the
remains are wild editing without checking). Unusable yet, and lacks the AC
decoding (but a step further in bitstream parsing)
patch by anonymous
author | michael |
---|---|
date | Fri, 04 Feb 2005 02:20:38 +0000 |
parents | 86d14aebd527 |
children | ef2149182f1c |
rev | line source |
---|---|
612 | 1 /* |
2 * simple arithmetic expression evaluator | |
3 * | |
4 * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at> | |
5 * | |
6 * This library is free software; you can redistribute it and/or | |
7 * modify it under the terms of the GNU Lesser General Public | |
8 * License as published by the Free Software Foundation; either | |
9 * version 2 of the License, or (at your option) any later version. | |
10 * | |
11 * This library is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Lesser General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Lesser General Public | |
17 * License along with this library; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 * | |
20 */ | |
21 | |
1106 | 22 /** |
23 * @file eval.c | |
24 * simple arithmetic expression evaluator. | |
25 * | |
612 | 26 * see http://joe.hotchkiss.com/programming/eval/eval.html |
27 */ | |
28 | |
1057 | 29 #include "avcodec.h" |
30 #include "mpegvideo.h" | |
31 | |
612 | 32 #include <stdio.h> |
33 #include <stdlib.h> | |
34 #include <string.h> | |
35 #include <math.h> | |
36 | |
614
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
37 #ifndef NAN |
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
38 #define NAN 0 |
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
39 #endif |
b786f15df503
NAN doesnt exist on FreeBSD patch by (Rmi Guyomarch <rguyom at pobox dot com>)
michaelni
parents:
612
diff
changeset
|
40 |
627 | 41 #ifndef M_PI |
42 #define M_PI 3.14159265358979323846 | |
43 #endif | |
44 | |
612 | 45 typedef struct Parser{ |
46 int stack_index; | |
47 char *s; | |
48 double *const_value; | |
1057 | 49 const char **const_name; // NULL terminated |
612 | 50 double (**func1)(void *, double a); // NULL terminated |
1057 | 51 const char **func1_name; // NULL terminated |
612 | 52 double (**func2)(void *, double a, double b); // NULL terminated |
53 char **func2_name; // NULL terminated | |
54 void *opaque; | |
55 } Parser; | |
56 | |
2434 | 57 static double evalExpression(Parser *p); |
612 | 58 |
1057 | 59 static int strmatch(const char *s, const char *prefix){ |
612 | 60 int i; |
61 for(i=0; prefix[i]; i++){ | |
62 if(prefix[i] != s[i]) return 0; | |
63 } | |
64 return 1; | |
65 } | |
66 | |
2434 | 67 static double evalPrimary(Parser *p){ |
612 | 68 double d, d2=NAN; |
69 char *next= p->s; | |
70 int i; | |
71 | |
72 /* number */ | |
73 d= strtod(p->s, &next); | |
74 if(next != p->s){ | |
75 p->s= next; | |
2434 | 76 return d; |
612 | 77 } |
78 | |
79 /* named constants */ | |
2433 | 80 for(i=0; p->const_name && p->const_name[i]; i++){ |
612 | 81 if(strmatch(p->s, p->const_name[i])){ |
82 p->s+= strlen(p->const_name[i]); | |
2434 | 83 return p->const_value[i]; |
612 | 84 } |
85 } | |
86 | |
87 p->s= strchr(p->s, '('); | |
88 if(p->s==NULL){ | |
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1106
diff
changeset
|
89 av_log(NULL, AV_LOG_ERROR, "Parser: missing ( in \"%s\"\n", next); |
2434 | 90 return NAN; |
612 | 91 } |
92 p->s++; // "(" | |
2434 | 93 d= evalExpression(p); |
1815 | 94 if(p->s[0]== ','){ |
95 p->s++; // "," | |
2434 | 96 d2= evalExpression(p); |
612 | 97 } |
1815 | 98 if(p->s[0] != ')'){ |
99 av_log(NULL, AV_LOG_ERROR, "Parser: missing ) in \"%s\"\n", next); | |
2434 | 100 return NAN; |
1815 | 101 } |
102 p->s++; // ")" | |
612 | 103 |
104 if( strmatch(next, "sinh" ) ) d= sinh(d); | |
105 else if( strmatch(next, "cosh" ) ) d= cosh(d); | |
106 else if( strmatch(next, "tanh" ) ) d= tanh(d); | |
107 else if( strmatch(next, "sin" ) ) d= sin(d); | |
108 else if( strmatch(next, "cos" ) ) d= cos(d); | |
109 else if( strmatch(next, "tan" ) ) d= tan(d); | |
110 else if( strmatch(next, "exp" ) ) d= exp(d); | |
111 else if( strmatch(next, "log" ) ) d= log(d); | |
112 else if( strmatch(next, "squish") ) d= 1/(1+exp(4*d)); | |
113 else if( strmatch(next, "gauss" ) ) d= exp(-d*d/2)/sqrt(2*M_PI); | |
1057 | 114 else if( strmatch(next, "abs" ) ) d= fabs(d); |
612 | 115 else if( strmatch(next, "max" ) ) d= d > d2 ? d : d2; |
116 else if( strmatch(next, "min" ) ) d= d < d2 ? d : d2; | |
117 else if( strmatch(next, "gt" ) ) d= d > d2 ? 1.0 : 0.0; | |
1815 | 118 else if( strmatch(next, "gte" ) ) d= d >= d2 ? 1.0 : 0.0; |
612 | 119 else if( strmatch(next, "lt" ) ) d= d > d2 ? 0.0 : 1.0; |
1815 | 120 else if( strmatch(next, "lte" ) ) d= d >= d2 ? 0.0 : 1.0; |
612 | 121 else if( strmatch(next, "eq" ) ) d= d == d2 ? 1.0 : 0.0; |
2434 | 122 else if( strmatch(next, "(" ) ) d= d; |
612 | 123 // else if( strmatch(next, "l1" ) ) d= 1 + d2*(d - 1); |
124 // else if( strmatch(next, "sq01" ) ) d= (d >= 0.0 && d <=1.0) ? 1.0 : 0.0; | |
125 else{ | |
126 for(i=0; p->func1_name && p->func1_name[i]; i++){ | |
127 if(strmatch(next, p->func1_name[i])){ | |
2434 | 128 return p->func1[i](p->opaque, d); |
612 | 129 } |
130 } | |
131 | |
132 for(i=0; p->func2_name && p->func2_name[i]; i++){ | |
133 if(strmatch(next, p->func2_name[i])){ | |
2434 | 134 return p->func2[i](p->opaque, d, d2); |
612 | 135 } |
136 } | |
137 | |
2433 | 138 av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next); |
2434 | 139 return NAN; |
612 | 140 } |
2433 | 141 |
2434 | 142 return d; |
612 | 143 } |
2436 | 144 |
2434 | 145 static double evalPow(Parser *p){ |
2436 | 146 int sign= (*p->s == '+') - (*p->s == '-'); |
147 p->s += sign&1; | |
148 return (sign|1) * evalPrimary(p); | |
2434 | 149 } |
612 | 150 |
2434 | 151 static double evalFactor(Parser *p){ |
152 double ret= evalPow(p); | |
153 while(p->s[0]=='^'){ | |
612 | 154 p->s++; |
2434 | 155 ret= pow(ret, evalPow(p)); |
612 | 156 } |
2434 | 157 return ret; |
612 | 158 } |
159 | |
2434 | 160 static double evalTerm(Parser *p){ |
161 double ret= evalFactor(p); | |
162 while(p->s[0]=='*' || p->s[0]=='/'){ | |
163 if(*p->s++ == '*') ret*= evalFactor(p); | |
164 else ret/= evalFactor(p); | |
612 | 165 } |
2434 | 166 return ret; |
612 | 167 } |
168 | |
2434 | 169 static double evalExpression(Parser *p){ |
2436 | 170 double ret= 0; |
612 | 171 |
2434 | 172 if(p->stack_index <= 0) //protect against stack overflows |
173 return NAN; | |
174 p->stack_index--; | |
175 | |
2436 | 176 do{ |
177 ret += evalTerm(p); | |
178 }while(*p->s == '+' || *p->s == '-'); | |
612 | 179 |
2434 | 180 p->stack_index++; |
612 | 181 |
2434 | 182 return ret; |
612 | 183 } |
184 | |
1057 | 185 double ff_eval(char *s, double *const_value, const char **const_name, |
186 double (**func1)(void *, double), const char **func1_name, | |
612 | 187 double (**func2)(void *, double, double), char **func2_name, |
188 void *opaque){ | |
189 Parser p; | |
190 | |
2434 | 191 p.stack_index=100; |
612 | 192 p.s= s; |
193 p.const_value= const_value; | |
194 p.const_name = const_name; | |
195 p.func1 = func1; | |
196 p.func1_name = func1_name; | |
197 p.func2 = func2; | |
198 p.func2_name = func2_name; | |
199 p.opaque = opaque; | |
200 | |
2434 | 201 return evalExpression(&p); |
612 | 202 } |
2433 | 203 |
204 #ifdef TEST | |
205 #undef printf | |
206 static double const_values[]={ | |
207 M_PI, | |
208 M_E, | |
209 0 | |
210 }; | |
211 static const char *const_names[]={ | |
212 "PI", | |
213 "E", | |
214 0 | |
215 }; | |
216 main(){ | |
2436 | 217 int i; |
2433 | 218 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)); |
2436 | 219 |
220 for(i=0; i<1050; i++){ | |
221 START_TIMER | |
222 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); | |
223 STOP_TIMER("ff_eval") | |
224 } | |
2433 | 225 } |
226 #endif |