## ffmpeg / libavcodec / eval.c @ 983e3246

History | View | Annotate | Download (6.43 KB)

1 | 3aa102be | Michael Niedermayer | ```
/*
``` |
---|---|---|---|

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 | |||

22 | 983e3246 | Michael Niedermayer | ```
/**
``` |

23 | ```
* @file eval.c
``` |
||

24 | ```
* simple arithmetic expression evaluator.
``` |
||

25 | ```
*
``` |
||

26 | 3aa102be | Michael Niedermayer | ```
* see http://joe.hotchkiss.com/programming/eval/eval.html
``` |

27 | ```
*/
``` |
||

28 | |||

29 | 5c91a675 | Zdenek Kabelac | #include "avcodec.h" |

30 | #include "mpegvideo.h" |
||

31 | |||

32 | 3aa102be | Michael Niedermayer | #include <stdio.h> |

33 | #include <stdlib.h> |
||

34 | #include <string.h> |
||

35 | #include <math.h> |
||

36 | |||

37 | d0d816d8 | RĂ©mi Guyomarch | ```
#ifndef NAN
``` |

38 | #define NAN 0 |
||

39 | ```
#endif
``` |
||

40 | |||

41 | 471d7dc3 | Michael Niedermayer | ```
#ifndef M_PI
``` |

42 | #define M_PI 3.14159265358979323846 |
||

43 | ```
#endif
``` |
||

44 | |||

45 | 3aa102be | Michael Niedermayer | #define STACK_SIZE 100 |

46 | |||

47 | typedef struct Parser{ |
||

48 | ```
double stack[STACK_SIZE];
``` |
||

49 | ```
int stack_index;
``` |
||

50 | ```
char *s;
``` |
||

51 | ```
double *const_value;
``` |
||

52 | 5c91a675 | Zdenek Kabelac | const char **const_name; // NULL terminated |

53 | 3aa102be | Michael Niedermayer | double (**func1)(void *, double a); // NULL terminated |

54 | 5c91a675 | Zdenek Kabelac | const char **func1_name; // NULL terminated |

55 | 3aa102be | Michael Niedermayer | double (**func2)(void *, double a, double b); // NULL terminated |

56 | char **func2_name; // NULL terminated |
||

57 | ```
void *opaque;
``` |
||

58 | } Parser; |
||

59 | |||

60 | static void evalExpression(Parser *p); |
||

61 | |||

62 | static void push(Parser *p, double d){ |
||

63 | if(p->stack_index+1>= STACK_SIZE){ |
||

64 | ```
fprintf(stderr, "stack overflow in the parser\n");
``` |
||

65 | ```
return;
``` |
||

66 | } |
||

67 | p->stack[ p->stack_index++ ]= d; |
||

68 | ```
//printf("push %f\n", d); fflush(stdout);
``` |
||

69 | } |
||

70 | |||

71 | static double pop(Parser *p){ |
||

72 | if(p->stack_index<=0){ |
||

73 | ```
fprintf(stderr, "stack underflow in the parser\n");
``` |
||

74 | ```
return NAN;
``` |
||

75 | } |
||

76 | ```
//printf("pop\n"); fflush(stdout);
``` |
||

77 | ```
return p->stack[ --p->stack_index ];
``` |
||

78 | } |
||

79 | |||

80 | 5c91a675 | Zdenek Kabelac | static int strmatch(const char *s, const char *prefix){ |

81 | 3aa102be | Michael Niedermayer | ```
int i;
``` |

82 | for(i=0; prefix[i]; i++){ |
||

83 | if(prefix[i] != s[i]) return 0; |
||

84 | } |
||

85 | return 1; |
||

86 | } |
||

87 | |||

88 | static void evalPrimary(Parser *p){ |
||

89 | ```
double d, d2=NAN;
``` |
||

90 | ```
char *next= p->s;
``` |
||

91 | ```
int i;
``` |
||

92 | |||

93 | ```
/* number */
``` |
||

94 | d= strtod(p->s, &next); |
||

95 | ```
if(next != p->s){
``` |
||

96 | push(p, d); |
||

97 | p->s= next; |
||

98 | ```
return;
``` |
||

99 | } |
||

100 | |||

101 | ```
/* named constants */
``` |
||

102 | for(i=0; p->const_name[i]; i++){ |
||

103 | ```
if(strmatch(p->s, p->const_name[i])){
``` |
||

104 | push(p, p->const_value[i]); |
||

105 | p->s+= strlen(p->const_name[i]); |
||

106 | ```
return;
``` |
||

107 | } |
||

108 | } |
||

109 | |||

110 | ```
p->s= strchr(p->s, '(');
``` |
||

111 | if(p->s==NULL){ |
||

112 | ```
fprintf(stderr, "Parser: missing ( in \"%s\"\n", next);
``` |
||

113 | ```
return;
``` |
||

114 | } |
||

115 | ```
p->s++; // "("
``` |
||

116 | evalExpression(p); |
||

117 | d= pop(p); |
||

118 | ```
p->s++; // ")" or ","
``` |
||

119 | if(p->s[-1]== ','){ |
||

120 | evalExpression(p); |
||

121 | d2= pop(p); |
||

122 | ```
p->s++; // ")"
``` |
||

123 | } |
||

124 | |||

125 | if( strmatch(next, "sinh" ) ) d= sinh(d); |
||

126 | else if( strmatch(next, "cosh" ) ) d= cosh(d); |
||

127 | else if( strmatch(next, "tanh" ) ) d= tanh(d); |
||

128 | else if( strmatch(next, "sin" ) ) d= sin(d); |
||

129 | else if( strmatch(next, "cos" ) ) d= cos(d); |
||

130 | else if( strmatch(next, "tan" ) ) d= tan(d); |
||

131 | else if( strmatch(next, "exp" ) ) d= exp(d); |
||

132 | else if( strmatch(next, "log" ) ) d= log(d); |
||

133 | else if( strmatch(next, "squish") ) d= 1/(1+exp(4*d)); |
||

134 | else if( strmatch(next, "gauss" ) ) d= exp(-d*d/2)/sqrt(2*M_PI); |
||

135 | 5c91a675 | Zdenek Kabelac | else if( strmatch(next, "abs" ) ) d= fabs(d); |

136 | 3aa102be | Michael Niedermayer | else if( strmatch(next, "max" ) ) d= d > d2 ? d : d2; |

137 | else if( strmatch(next, "min" ) ) d= d < d2 ? d : d2; |
||

138 | else if( strmatch(next, "gt" ) ) d= d > d2 ? 1.0 : 0.0; |
||

139 | else if( strmatch(next, "lt" ) ) d= d > d2 ? 0.0 : 1.0; |
||

140 | else if( strmatch(next, "eq" ) ) d= d == d2 ? 1.0 : 0.0; |
||

141 | ```
// else if( strmatch(next, "l1" ) ) d= 1 + d2*(d - 1);
``` |
||

142 | ```
// else if( strmatch(next, "sq01" ) ) d= (d >= 0.0 && d <=1.0) ? 1.0 : 0.0;
``` |
||

143 | ```
else{
``` |
||

144 | int error=1; |
||

145 | for(i=0; p->func1_name && p->func1_name[i]; i++){ |
||

146 | ```
if(strmatch(next, p->func1_name[i])){
``` |
||

147 | d= p->func1[i](p->opaque, d); |
||

148 | ```
error=0;
``` |
||

149 | ```
break;
``` |
||

150 | } |
||

151 | } |
||

152 | |||

153 | for(i=0; p->func2_name && p->func2_name[i]; i++){ |
||

154 | ```
if(strmatch(next, p->func2_name[i])){
``` |
||

155 | d= p->func2[i](p->opaque, d, d2); |
||

156 | ```
error=0;
``` |
||

157 | ```
break;
``` |
||

158 | } |
||

159 | } |
||

160 | |||

161 | ```
if(error){
``` |
||

162 | ```
fprintf(stderr, "Parser: unknown function in \"%s\"\n", next);
``` |
||

163 | ```
return;
``` |
||

164 | } |
||

165 | } |
||

166 | |||

167 | if(p->s[-1]!= ')'){ |
||

168 | ```
fprintf(stderr, "Parser: missing ) in \"%s\"\n", next);
``` |
||

169 | ```
return;
``` |
||

170 | } |
||

171 | push(p, d); |
||

172 | } |
||

173 | |||

174 | static void evalPow(Parser *p){ |
||

175 | int neg= 0; |
||

176 | if(p->s[0]=='+') p->s++; |
||

177 | |||

178 | if(p->s[0]=='-'){ |
||

179 | ```
neg= 1;
``` |
||

180 | p->s++; |
||

181 | } |
||

182 | |||

183 | if(p->s[0]=='('){ |
||

184 | p->s++;; |
||

185 | evalExpression(p); |
||

186 | |||

187 | if(p->s[0]!=')') |
||

188 | ```
fprintf(stderr, "Parser: missing )\n");
``` |
||

189 | p->s++; |
||

190 | ```
}else{
``` |
||

191 | evalPrimary(p); |
||

192 | } |
||

193 | |||

194 | ```
if(neg) push(p, -pop(p));
``` |
||

195 | } |
||

196 | |||

197 | static void evalFactor(Parser *p){ |
||

198 | evalPow(p); |
||

199 | while(p->s[0]=='^'){ |
||

200 | ```
double d;
``` |
||

201 | |||

202 | p->s++; |
||

203 | evalPow(p); |
||

204 | d= pop(p); |
||

205 | push(p, pow(pop(p), d)); |
||

206 | } |
||

207 | } |
||

208 | |||

209 | static void evalTerm(Parser *p){ |
||

210 | evalFactor(p); |
||

211 | while(p->s[0]=='*' || p->s[0]=='/'){ |
||

212 | int inv= p->s[0]=='/'; |
||

213 | ```
double d;
``` |
||

214 | |||

215 | p->s++; |
||

216 | evalFactor(p); |
||

217 | d= pop(p); |
||

218 | if(inv) d= 1.0/d; |
||

219 | push(p, d * pop(p)); |
||

220 | } |
||

221 | } |
||

222 | |||

223 | static void evalExpression(Parser *p){ |
||

224 | evalTerm(p); |
||

225 | while(p->s[0]=='+' || p->s[0]=='-'){ |
||

226 | int sign= p->s[0]=='-'; |
||

227 | ```
double d;
``` |
||

228 | |||

229 | p->s++; |
||

230 | evalTerm(p); |
||

231 | d= pop(p); |
||

232 | ```
if(sign) d= -d;
``` |
||

233 | push(p, d + pop(p)); |
||

234 | } |
||

235 | } |
||

236 | |||

237 | 5c91a675 | Zdenek Kabelac | double ff_eval(char *s, double *const_value, const char **const_name, |

238 | double (**func1)(void *, double), const char **func1_name, |
||

239 | 3aa102be | Michael Niedermayer | double (**func2)(void *, double, double), char **func2_name, |

240 | ```
void *opaque){
``` |
||

241 | Parser p; |
||

242 | |||

243 | ```
p.stack_index=0;
``` |
||

244 | p.s= s; |
||

245 | p.const_value= const_value; |
||

246 | p.const_name = const_name; |
||

247 | p.func1 = func1; |
||

248 | p.func1_name = func1_name; |
||

249 | p.func2 = func2; |
||

250 | p.func2_name = func2_name; |
||

251 | p.opaque = opaque; |
||

252 | |||

253 | evalExpression(&p); |
||

254 | ```
return pop(&p);
``` |
||

255 | } |