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