00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00029 #include "avutil.h"
00030 #include "eval.h"
00031
00032 typedef struct Parser {
00033 const AVClass *class;
00034 int stack_index;
00035 char *s;
00036 const double *const_values;
00037 const char * const *const_names;
00038 double (* const *funcs1)(void *, double a);
00039 const char * const *func1_names;
00040 double (* const *funcs2)(void *, double a, double b);
00041 const char * const *func2_names;
00042 void *opaque;
00043 int log_offset;
00044 void *log_ctx;
00045 #define VARS 10
00046 double var[VARS];
00047 } Parser;
00048
00049 static const AVClass class = { "Eval", av_default_item_name, NULL, LIBAVUTIL_VERSION_INT, offsetof(Parser,log_offset), offsetof(Parser,log_ctx) };
00050
00051 static const int8_t si_prefixes['z' - 'E' + 1] = {
00052 ['y'-'E']= -24,
00053 ['z'-'E']= -21,
00054 ['a'-'E']= -18,
00055 ['f'-'E']= -15,
00056 ['p'-'E']= -12,
00057 ['n'-'E']= - 9,
00058 ['u'-'E']= - 6,
00059 ['m'-'E']= - 3,
00060 ['c'-'E']= - 2,
00061 ['d'-'E']= - 1,
00062 ['h'-'E']= 2,
00063 ['k'-'E']= 3,
00064 ['K'-'E']= 3,
00065 ['M'-'E']= 6,
00066 ['G'-'E']= 9,
00067 ['T'-'E']= 12,
00068 ['P'-'E']= 15,
00069 ['E'-'E']= 18,
00070 ['Z'-'E']= 21,
00071 ['Y'-'E']= 24,
00072 };
00073
00074 double av_strtod(const char *numstr, char **tail)
00075 {
00076 double d;
00077 char *next;
00078 if(numstr[0]=='0' && (numstr[1]|0x20)=='x') {
00079 d = strtoul(numstr, &next, 16);
00080 } else
00081 d = strtod(numstr, &next);
00082
00083 if (next!=numstr) {
00084 if (*next >= 'E' && *next <= 'z') {
00085 int e= si_prefixes[*next - 'E'];
00086 if (e) {
00087 if (next[1] == 'i') {
00088 d*= pow( 2, e/0.3);
00089 next+=2;
00090 } else {
00091 d*= pow(10, e);
00092 next++;
00093 }
00094 }
00095 }
00096
00097 if (*next=='B') {
00098 d*=8;
00099 next++;
00100 }
00101 }
00102
00103
00104 if (tail)
00105 *tail = next;
00106 return d;
00107 }
00108
00109 #define IS_IDENTIFIER_CHAR(c) ((c) - '0' <= 9U || (c) - 'a' <= 25U || (c) - 'A' <= 25U || (c) == '_')
00110
00111 static int strmatch(const char *s, const char *prefix)
00112 {
00113 int i;
00114 for (i=0; prefix[i]; i++) {
00115 if (prefix[i] != s[i]) return 0;
00116 }
00117
00118 return !IS_IDENTIFIER_CHAR(s[i]);
00119 }
00120
00121 struct AVExpr {
00122 enum {
00123 e_value, e_const, e_func0, e_func1, e_func2,
00124 e_squish, e_gauss, e_ld, e_isnan,
00125 e_mod, e_max, e_min, e_eq, e_gt, e_gte,
00126 e_pow, e_mul, e_div, e_add,
00127 e_last, e_st, e_while, e_floor, e_ceil, e_trunc,
00128 e_sqrt, e_not,
00129 } type;
00130 double value;
00131 union {
00132 int const_index;
00133 double (*func0)(double);
00134 double (*func1)(void *, double);
00135 double (*func2)(void *, double, double);
00136 } a;
00137 struct AVExpr *param[2];
00138 };
00139
00140 static double eval_expr(Parser *p, AVExpr *e)
00141 {
00142 switch (e->type) {
00143 case e_value: return e->value;
00144 case e_const: return e->value * p->const_values[e->a.const_index];
00145 case e_func0: return e->value * e->a.func0(eval_expr(p, e->param[0]));
00146 case e_func1: return e->value * e->a.func1(p->opaque, eval_expr(p, e->param[0]));
00147 case e_func2: return e->value * e->a.func2(p->opaque, eval_expr(p, e->param[0]), eval_expr(p, e->param[1]));
00148 case e_squish: return 1/(1+exp(4*eval_expr(p, e->param[0])));
00149 case e_gauss: { double d = eval_expr(p, e->param[0]); return exp(-d*d/2)/sqrt(2*M_PI); }
00150 case e_ld: return e->value * p->var[av_clip(eval_expr(p, e->param[0]), 0, VARS-1)];
00151 case e_isnan: return e->value * !!isnan(eval_expr(p, e->param[0]));
00152 case e_floor: return e->value * floor(eval_expr(p, e->param[0]));
00153 case e_ceil : return e->value * ceil (eval_expr(p, e->param[0]));
00154 case e_trunc: return e->value * trunc(eval_expr(p, e->param[0]));
00155 case e_sqrt: return e->value * sqrt (eval_expr(p, e->param[0]));
00156 case e_not: return e->value * eval_expr(p, e->param[0]) == 0;
00157 case e_while: {
00158 double d = NAN;
00159 while (eval_expr(p, e->param[0]))
00160 d=eval_expr(p, e->param[1]);
00161 return d;
00162 }
00163 default: {
00164 double d = eval_expr(p, e->param[0]);
00165 double d2 = eval_expr(p, e->param[1]);
00166 switch (e->type) {
00167 case e_mod: return e->value * (d - floor(d/d2)*d2);
00168 case e_max: return e->value * (d > d2 ? d : d2);
00169 case e_min: return e->value * (d < d2 ? d : d2);
00170 case e_eq: return e->value * (d == d2 ? 1.0 : 0.0);
00171 case e_gt: return e->value * (d > d2 ? 1.0 : 0.0);
00172 case e_gte: return e->value * (d >= d2 ? 1.0 : 0.0);
00173 case e_pow: return e->value * pow(d, d2);
00174 case e_mul: return e->value * (d * d2);
00175 case e_div: return e->value * (d / d2);
00176 case e_add: return e->value * (d + d2);
00177 case e_last:return e->value * d2;
00178 case e_st : return e->value * (p->var[av_clip(d, 0, VARS-1)]= d2);
00179 }
00180 }
00181 }
00182 return NAN;
00183 }
00184
00185 static int parse_expr(AVExpr **e, Parser *p);
00186
00187 void av_expr_free(AVExpr *e)
00188 {
00189 if (!e) return;
00190 av_expr_free(e->param[0]);
00191 av_expr_free(e->param[1]);
00192 av_freep(&e);
00193 }
00194
00195 static int parse_primary(AVExpr **e, Parser *p)
00196 {
00197 AVExpr *d = av_mallocz(sizeof(AVExpr));
00198 char *next = p->s, *s0 = p->s;
00199 int ret, i;
00200
00201 if (!d)
00202 return AVERROR(ENOMEM);
00203
00204
00205 d->value = av_strtod(p->s, &next);
00206 if (next != p->s) {
00207 d->type = e_value;
00208 p->s= next;
00209 *e = d;
00210 return 0;
00211 }
00212 d->value = 1;
00213
00214
00215 for (i=0; p->const_names && p->const_names[i]; i++) {
00216 if (strmatch(p->s, p->const_names[i])) {
00217 p->s+= strlen(p->const_names[i]);
00218 d->type = e_const;
00219 d->a.const_index = i;
00220 *e = d;
00221 return 0;
00222 }
00223 }
00224
00225 p->s= strchr(p->s, '(');
00226 if (p->s==NULL) {
00227 av_log(p, AV_LOG_ERROR, "Undefined constant or missing '(' in '%s'\n", s0);
00228 p->s= next;
00229 av_expr_free(d);
00230 return AVERROR(EINVAL);
00231 }
00232 p->s++;
00233 if (*next == '(') {
00234 av_freep(&d);
00235 if ((ret = parse_expr(&d, p)) < 0)
00236 return ret;
00237 if (p->s[0] != ')') {
00238 av_log(p, AV_LOG_ERROR, "Missing ')' in '%s'\n", s0);
00239 av_expr_free(d);
00240 return AVERROR(EINVAL);
00241 }
00242 p->s++;
00243 *e = d;
00244 return 0;
00245 }
00246 if ((ret = parse_expr(&(d->param[0]), p)) < 0) {
00247 av_expr_free(d);
00248 return ret;
00249 }
00250 if (p->s[0]== ',') {
00251 p->s++;
00252 parse_expr(&d->param[1], p);
00253 }
00254 if (p->s[0] != ')') {
00255 av_log(p, AV_LOG_ERROR, "Missing ')' or too many args in '%s'\n", s0);
00256 av_expr_free(d);
00257 return AVERROR(EINVAL);
00258 }
00259 p->s++;
00260
00261 d->type = e_func0;
00262 if (strmatch(next, "sinh" )) d->a.func0 = sinh;
00263 else if (strmatch(next, "cosh" )) d->a.func0 = cosh;
00264 else if (strmatch(next, "tanh" )) d->a.func0 = tanh;
00265 else if (strmatch(next, "sin" )) d->a.func0 = sin;
00266 else if (strmatch(next, "cos" )) d->a.func0 = cos;
00267 else if (strmatch(next, "tan" )) d->a.func0 = tan;
00268 else if (strmatch(next, "atan" )) d->a.func0 = atan;
00269 else if (strmatch(next, "asin" )) d->a.func0 = asin;
00270 else if (strmatch(next, "acos" )) d->a.func0 = acos;
00271 else if (strmatch(next, "exp" )) d->a.func0 = exp;
00272 else if (strmatch(next, "log" )) d->a.func0 = log;
00273 else if (strmatch(next, "abs" )) d->a.func0 = fabs;
00274 else if (strmatch(next, "squish")) d->type = e_squish;
00275 else if (strmatch(next, "gauss" )) d->type = e_gauss;
00276 else if (strmatch(next, "mod" )) d->type = e_mod;
00277 else if (strmatch(next, "max" )) d->type = e_max;
00278 else if (strmatch(next, "min" )) d->type = e_min;
00279 else if (strmatch(next, "eq" )) d->type = e_eq;
00280 else if (strmatch(next, "gte" )) d->type = e_gte;
00281 else if (strmatch(next, "gt" )) d->type = e_gt;
00282 else if (strmatch(next, "lte" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gt; }
00283 else if (strmatch(next, "lt" )) { AVExpr *tmp = d->param[1]; d->param[1] = d->param[0]; d->param[0] = tmp; d->type = e_gte; }
00284 else if (strmatch(next, "ld" )) d->type = e_ld;
00285 else if (strmatch(next, "isnan" )) d->type = e_isnan;
00286 else if (strmatch(next, "st" )) d->type = e_st;
00287 else if (strmatch(next, "while" )) d->type = e_while;
00288 else if (strmatch(next, "floor" )) d->type = e_floor;
00289 else if (strmatch(next, "ceil" )) d->type = e_ceil;
00290 else if (strmatch(next, "trunc" )) d->type = e_trunc;
00291 else if (strmatch(next, "sqrt" )) d->type = e_sqrt;
00292 else if (strmatch(next, "not" )) d->type = e_not;
00293 else if (strmatch(next, "pow" )) d->type = e_pow;
00294 else {
00295 for (i=0; p->func1_names && p->func1_names[i]; i++) {
00296 if (strmatch(next, p->func1_names[i])) {
00297 d->a.func1 = p->funcs1[i];
00298 d->type = e_func1;
00299 *e = d;
00300 return 0;
00301 }
00302 }
00303
00304 for (i=0; p->func2_names && p->func2_names[i]; i++) {
00305 if (strmatch(next, p->func2_names[i])) {
00306 d->a.func2 = p->funcs2[i];
00307 d->type = e_func2;
00308 *e = d;
00309 return 0;
00310 }
00311 }
00312
00313 av_log(p, AV_LOG_ERROR, "Unknown function in '%s'\n", s0);
00314 av_expr_free(d);
00315 return AVERROR(EINVAL);
00316 }
00317
00318 *e = d;
00319 return 0;
00320 }
00321
00322 static AVExpr *new_eval_expr(int type, int value, AVExpr *p0, AVExpr *p1)
00323 {
00324 AVExpr *e = av_mallocz(sizeof(AVExpr));
00325 if (!e)
00326 return NULL;
00327 e->type =type ;
00328 e->value =value ;
00329 e->param[0] =p0 ;
00330 e->param[1] =p1 ;
00331 return e;
00332 }
00333
00334 static int parse_pow(AVExpr **e, Parser *p, int *sign)
00335 {
00336 *sign= (*p->s == '+') - (*p->s == '-');
00337 p->s += *sign&1;
00338 return parse_primary(e, p);
00339 }
00340
00341 static int parse_factor(AVExpr **e, Parser *p)
00342 {
00343 int sign, sign2, ret;
00344 AVExpr *e0, *e1, *e2;
00345 if ((ret = parse_pow(&e0, p, &sign)) < 0)
00346 return ret;
00347 while(p->s[0]=='^'){
00348 e1 = e0;
00349 p->s++;
00350 if ((ret = parse_pow(&e2, p, &sign2)) < 0) {
00351 av_expr_free(e1);
00352 return ret;
00353 }
00354 e0 = new_eval_expr(e_pow, 1, e1, e2);
00355 if (!e0) {
00356 av_expr_free(e1);
00357 av_expr_free(e2);
00358 return AVERROR(ENOMEM);
00359 }
00360 if (e0->param[1]) e0->param[1]->value *= (sign2|1);
00361 }
00362 if (e0) e0->value *= (sign|1);
00363
00364 *e = e0;
00365 return 0;
00366 }
00367
00368 static int parse_term(AVExpr **e, Parser *p)
00369 {
00370 int ret;
00371 AVExpr *e0, *e1, *e2;
00372 if ((ret = parse_factor(&e0, p)) < 0)
00373 return ret;
00374 while (p->s[0]=='*' || p->s[0]=='/') {
00375 int c= *p->s++;
00376 e1 = e0;
00377 if ((ret = parse_factor(&e2, p)) < 0) {
00378 av_expr_free(e1);
00379 return ret;
00380 }
00381 e0 = new_eval_expr(c == '*' ? e_mul : e_div, 1, e1, e2);
00382 if (!e0) {
00383 av_expr_free(e1);
00384 av_expr_free(e2);
00385 return AVERROR(ENOMEM);
00386 }
00387 }
00388 *e = e0;
00389 return 0;
00390 }
00391
00392 static int parse_subexpr(AVExpr **e, Parser *p)
00393 {
00394 int ret;
00395 AVExpr *e0, *e1, *e2;
00396 if ((ret = parse_term(&e0, p)) < 0)
00397 return ret;
00398 while (*p->s == '+' || *p->s == '-') {
00399 e1 = e0;
00400 if ((ret = parse_term(&e2, p)) < 0) {
00401 av_expr_free(e1);
00402 return ret;
00403 }
00404 e0 = new_eval_expr(e_add, 1, e1, e2);
00405 if (!e0) {
00406 av_expr_free(e1);
00407 av_expr_free(e2);
00408 return AVERROR(ENOMEM);
00409 }
00410 };
00411
00412 *e = e0;
00413 return 0;
00414 }
00415
00416 static int parse_expr(AVExpr **e, Parser *p)
00417 {
00418 int ret;
00419 AVExpr *e0, *e1, *e2;
00420 if (p->stack_index <= 0)
00421 return AVERROR(EINVAL);
00422 p->stack_index--;
00423
00424 if ((ret = parse_subexpr(&e0, p)) < 0)
00425 return ret;
00426 while (*p->s == ';') {
00427 p->s++;
00428 e1 = e0;
00429 if ((ret = parse_subexpr(&e2, p)) < 0) {
00430 av_expr_free(e1);
00431 return ret;
00432 }
00433 e0 = new_eval_expr(e_last, 1, e1, e2);
00434 if (!e0) {
00435 av_expr_free(e1);
00436 av_expr_free(e2);
00437 return AVERROR(ENOMEM);
00438 }
00439 };
00440
00441 p->stack_index++;
00442 *e = e0;
00443 return 0;
00444 }
00445
00446 static int verify_expr(AVExpr *e)
00447 {
00448 if (!e) return 0;
00449 switch (e->type) {
00450 case e_value:
00451 case e_const: return 1;
00452 case e_func0:
00453 case e_func1:
00454 case e_squish:
00455 case e_ld:
00456 case e_gauss:
00457 case e_isnan:
00458 case e_floor:
00459 case e_ceil:
00460 case e_trunc:
00461 case e_sqrt:
00462 case e_not:
00463 return verify_expr(e->param[0]);
00464 default: return verify_expr(e->param[0]) && verify_expr(e->param[1]);
00465 }
00466 }
00467
00468 int av_expr_parse(AVExpr **expr, const char *s,
00469 const char * const *const_names,
00470 const char * const *func1_names, double (* const *funcs1)(void *, double),
00471 const char * const *func2_names, double (* const *funcs2)(void *, double, double),
00472 int log_offset, void *log_ctx)
00473 {
00474 Parser p;
00475 AVExpr *e = NULL;
00476 char *w = av_malloc(strlen(s) + 1);
00477 char *wp = w;
00478 const char *s0 = s;
00479 int ret = 0;
00480
00481 if (!w)
00482 return AVERROR(ENOMEM);
00483
00484 while (*s)
00485 if (!isspace(*s++)) *wp++ = s[-1];
00486 *wp++ = 0;
00487
00488 p.class = &class;
00489 p.stack_index=100;
00490 p.s= w;
00491 p.const_names = const_names;
00492 p.funcs1 = funcs1;
00493 p.func1_names = func1_names;
00494 p.funcs2 = funcs2;
00495 p.func2_names = func2_names;
00496 p.log_offset = log_offset;
00497 p.log_ctx = log_ctx;
00498
00499 if ((ret = parse_expr(&e, &p)) < 0)
00500 goto end;
00501 if (*p.s) {
00502 av_expr_free(e);
00503 av_log(&p, AV_LOG_ERROR, "Invalid chars '%s' at the end of expression '%s'\n", p.s, s0);
00504 ret = AVERROR(EINVAL);
00505 goto end;
00506 }
00507 if (!verify_expr(e)) {
00508 av_expr_free(e);
00509 ret = AVERROR(EINVAL);
00510 goto end;
00511 }
00512 *expr = e;
00513 end:
00514 av_free(w);
00515 return ret;
00516 }
00517
00518 double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
00519 {
00520 Parser p;
00521
00522 p.const_values = const_values;
00523 p.opaque = opaque;
00524 return eval_expr(&p, e);
00525 }
00526
00527 int av_expr_parse_and_eval(double *d, const char *s,
00528 const char * const *const_names, const double *const_values,
00529 const char * const *func1_names, double (* const *funcs1)(void *, double),
00530 const char * const *func2_names, double (* const *funcs2)(void *, double, double),
00531 void *opaque, int log_offset, void *log_ctx)
00532 {
00533 AVExpr *e = NULL;
00534 int ret = av_expr_parse(&e, s, const_names, func1_names, funcs1, func2_names, funcs2, log_offset, log_ctx);
00535
00536 if (ret < 0) {
00537 *d = NAN;
00538 return ret;
00539 }
00540 *d = av_expr_eval(e, const_values, opaque);
00541 av_expr_free(e);
00542 return isnan(*d) ? AVERROR(EINVAL) : 0;
00543 }
00544
00545 #if FF_API_OLD_EVAL_NAMES
00546 int av_parse_expr(AVExpr **expr, const char *s,
00547 const char * const *const_names,
00548 const char * const *func1_names, double (* const *funcs1)(void *, double),
00549 const char * const *func2_names, double (* const *funcs2)(void *, double, double),
00550 int log_offset, void *log_ctx)
00551 {
00552 return av_expr_parse(expr, s, const_names, func1_names, funcs1, func2_names, funcs2,
00553 log_offset, log_ctx);
00554 }
00555
00556 double av_eval_expr(AVExpr *e, const double *const_values, void *opaque)
00557 {
00558 return av_expr_eval(e, const_values, opaque);
00559 }
00560
00561 int av_parse_and_eval_expr(double *res, const char *s,
00562 const char * const *const_names, const double *const_values,
00563 const char * const *func1_names, double (* const *funcs1)(void *, double),
00564 const char * const *func2_names, double (* const *funcs2)(void *, double, double),
00565 void *opaque, int log_offset, void *log_ctx)
00566 {
00567 return av_expr_parse_and_eval(res, s, const_names, const_values, func1_names, funcs1, func2_names, funcs2,
00568 opaque, log_offset, log_ctx);
00569 }
00570
00571 void av_free_expr(AVExpr *e)
00572 {
00573 av_expr_free(e);
00574 }
00575 #endif
00576
00577 #ifdef TEST
00578 #undef printf
00579 static double const_values[] = {
00580 M_PI,
00581 M_E,
00582 0
00583 };
00584
00585 static const char *const_names[] = {
00586 "PI",
00587 "E",
00588 0
00589 };
00590
00591 int main(void)
00592 {
00593 int i;
00594 double d;
00595 const char **expr, *exprs[] = {
00596 "",
00597 "1;2",
00598 "-20",
00599 "-PI",
00600 "+PI",
00601 "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
00602 "80G/80Gi"
00603 "1k",
00604 "1Gi",
00605 "1gi",
00606 "1GiFoo",
00607 "1k+1k",
00608 "1Gi*3foo",
00609 "foo",
00610 "foo(",
00611 "foo()",
00612 "foo)",
00613 "sin",
00614 "sin(",
00615 "sin()",
00616 "sin)",
00617 "sin 10",
00618 "sin(1,2,3)",
00619 "sin(1 )",
00620 "1",
00621 "1foo",
00622 "bar + PI + E + 100f*2 + foo",
00623 "13k + 12f - foo(1, 2)",
00624 "1gi",
00625 "1Gi",
00626 "st(0, 123)",
00627 "st(1, 123); ld(1)",
00628
00629 "st(0, 1); while(lte(ld(0), 100), st(1, ld(1)+ld(0));st(0, ld(0)+1)); ld(1)",
00630
00631 "st(1, 1); st(2, 2); st(0, 1); while(lte(ld(0),10), st(3, ld(1)+ld(2)); st(1, ld(2)); st(2, ld(3)); st(0, ld(0)+1)); ld(3)",
00632 "while(0, 10)",
00633 "st(0, 1); while(lte(ld(0),100), st(1, ld(1)+ld(0)); st(0, ld(0)+1))",
00634 "isnan(1)",
00635 "isnan(NAN)",
00636 "floor(NAN)",
00637 "floor(123.123)",
00638 "floor(-123.123)",
00639 "trunc(123.123)",
00640 "trunc(-123.123)",
00641 "ceil(123.123)",
00642 "ceil(-123.123)",
00643 "sqrt(1764)",
00644 "sqrt(-1)",
00645 "not(1)",
00646 "not(NAN)",
00647 "not(0)",
00648 "pow(0,1.23)",
00649 "pow(PI,1.23)",
00650 "PI^1.23",
00651 "pow(-1,1.23)",
00652 NULL
00653 };
00654
00655 for (expr = exprs; *expr; expr++) {
00656 printf("Evaluating '%s'\n", *expr);
00657 av_expr_parse_and_eval(&d, *expr,
00658 const_names, const_values,
00659 NULL, NULL, NULL, NULL, NULL, 0, NULL);
00660 printf("'%s' -> %f\n\n", *expr, d);
00661 }
00662
00663 av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
00664 const_names, const_values,
00665 NULL, NULL, NULL, NULL, NULL, 0, NULL);
00666 printf("%f == 12.7\n", d);
00667 av_expr_parse_and_eval(&d, "80G/80Gi",
00668 const_names, const_values,
00669 NULL, NULL, NULL, NULL, NULL, 0, NULL);
00670 printf("%f == 0.931322575\n", d);
00671
00672 for (i=0; i<1050; i++) {
00673 START_TIMER
00674 av_expr_parse_and_eval(&d, "1+(5-2)^(3-1)+1/2+sin(PI)-max(-2.2,-3.1)",
00675 const_names, const_values,
00676 NULL, NULL, NULL, NULL, NULL, 0, NULL);
00677 STOP_TIMER("av_expr_parse_and_eval")
00678 }
00679 return 0;
00680 }
00681 #endif