~ubuntu-dev/mplayer/ubuntu-feisty

« back to all changes in this revision

Viewing changes to libavcodec/eval.c

  • Committer: William Grant
  • Date: 2007-02-03 03:16:07 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: william.grant@ubuntu.org.au-20070203031607-08gc2ompbz6spt9i
Update to 1.0rc1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *
4
4
 * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
5
5
 *
6
 
 * This library is free software; you can redistribute it and/or
 
6
 * This file is part of FFmpeg.
 
7
 *
 
8
 * FFmpeg is free software; you can redistribute it and/or
7
9
 * modify it under the terms of the GNU Lesser General Public
8
10
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
 
11
 * version 2.1 of the License, or (at your option) any later version.
10
12
 *
11
 
 * This library is distributed in the hope that it will be useful,
 
13
 * FFmpeg is distributed in the hope that it will be useful,
12
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
16
 * Lesser General Public License for more details.
15
17
 *
16
18
 * 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
 
19
 * License along with FFmpeg; if not, write to the Free Software
18
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
21
 *
20
22
 */
35
37
#include <math.h>
36
38
 
37
39
#ifndef NAN
38
 
  #define NAN 0
 
40
  #define NAN 0.0/0.0
39
41
#endif
40
42
 
41
43
#ifndef M_PI
52
54
    double (**func2)(void *, double a, double b); // NULL terminated
53
55
    char **func2_name;          // NULL terminated
54
56
    void *opaque;
 
57
    char **error;
55
58
} Parser;
56
59
 
57
60
static double evalExpression(Parser *p);
58
61
 
 
62
static int8_t si_prefixes['z' - 'E' + 1]={
 
63
    ['y'-'E']= -24,
 
64
    ['z'-'E']= -21,
 
65
    ['a'-'E']= -18,
 
66
    ['f'-'E']= -15,
 
67
    ['p'-'E']= -12,
 
68
    ['n'-'E']= - 9,
 
69
    ['u'-'E']= - 6,
 
70
    ['m'-'E']= - 3,
 
71
    ['c'-'E']= - 2,
 
72
    ['d'-'E']= - 1,
 
73
    ['h'-'E']=   2,
 
74
    ['k'-'E']=   3,
 
75
    ['K'-'E']=   3,
 
76
    ['M'-'E']=   6,
 
77
    ['G'-'E']=   9,
 
78
    ['T'-'E']=  12,
 
79
    ['P'-'E']=  15,
 
80
    ['E'-'E']=  18,
 
81
    ['Z'-'E']=  21,
 
82
    ['Y'-'E']=  24,
 
83
};
 
84
 
 
85
/** strtod() function extended with 'k', 'M', 'G', 'ki', 'Mi', 'Gi' and 'B'
 
86
 * postfixes.  This allows using f.e. kB, MiB, G and B as a postfix. This
 
87
 * function assumes that the unit of numbers is bits not bytes.
 
88
 */
 
89
static double av_strtod(const char *name, char **tail) {
 
90
    double d;
 
91
    char *next;
 
92
    d = strtod(name, &next);
 
93
    /* if parsing succeeded, check for and interpret postfixes */
 
94
    if (next!=name) {
 
95
 
 
96
        if(*next >= 'E' && *next <= 'z'){
 
97
            int e= si_prefixes[*next - 'E'];
 
98
            if(e){
 
99
                if(next[1] == 'i'){
 
100
                    d*= pow( 2, e/0.3);
 
101
                    next+=2;
 
102
                }else{
 
103
                    d*= pow(10, e);
 
104
                    next++;
 
105
                }
 
106
            }
 
107
        }
 
108
 
 
109
        if(*next=='B') {
 
110
            d*=8;
 
111
            *next++;
 
112
        }
 
113
    }
 
114
    /* if requested, fill in tail with the position after the last parsed
 
115
       character */
 
116
    if (tail)
 
117
        *tail = next;
 
118
    return d;
 
119
}
 
120
 
59
121
static int strmatch(const char *s, const char *prefix){
60
122
    int i;
61
123
    for(i=0; prefix[i]; i++){
70
132
    int i;
71
133
 
72
134
    /* number */
73
 
    d= strtod(p->s, &next);
 
135
    d= av_strtod(p->s, &next);
74
136
    if(next != p->s){
75
137
        p->s= next;
76
138
        return d;
86
148
 
87
149
    p->s= strchr(p->s, '(');
88
150
    if(p->s==NULL){
89
 
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ( in \"%s\"\n", next);
 
151
        *p->error = "missing (";
 
152
        p->s= next;
90
153
        return NAN;
91
154
    }
92
155
    p->s++; // "("
96
159
        d2= evalExpression(p);
97
160
    }
98
161
    if(p->s[0] != ')'){
99
 
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ) in \"%s\"\n", next);
 
162
        *p->error = "missing )";
100
163
        return NAN;
101
164
    }
102
165
    p->s++; // ")"
107
170
    else if( strmatch(next, "sin"   ) ) d= sin(d);
108
171
    else if( strmatch(next, "cos"   ) ) d= cos(d);
109
172
    else if( strmatch(next, "tan"   ) ) d= tan(d);
 
173
    else if( strmatch(next, "atan"  ) ) d= atan(d);
 
174
    else if( strmatch(next, "asin"  ) ) d= asin(d);
 
175
    else if( strmatch(next, "acos"  ) ) d= acos(d);
110
176
    else if( strmatch(next, "exp"   ) ) d= exp(d);
111
177
    else if( strmatch(next, "log"   ) ) d= log(d);
112
178
    else if( strmatch(next, "squish") ) d= 1/(1+exp(4*d));
113
179
    else if( strmatch(next, "gauss" ) ) d= exp(-d*d/2)/sqrt(2*M_PI);
114
180
    else if( strmatch(next, "abs"   ) ) d= fabs(d);
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;
118
 
    else if( strmatch(next, "gte"    ) ) d= d >= d2 ? 1.0 : 0.0;
119
 
    else if( strmatch(next, "lt"    ) ) d= d > d2 ? 0.0 : 1.0;
120
 
    else if( strmatch(next, "lte"    ) ) d= d >= d2 ? 0.0 : 1.0;
 
181
    else if( strmatch(next, "mod"   ) ) d-= floor(d/d2)*d2;
 
182
    else if( strmatch(next, "max"   ) ) d= d >  d2 ?   d : d2;
 
183
    else if( strmatch(next, "min"   ) ) d= d <  d2 ?   d : d2;
 
184
    else if( strmatch(next, "gt"    ) ) d= d >  d2 ? 1.0 : 0.0;
 
185
    else if( strmatch(next, "gte"   ) ) d= d >= d2 ? 1.0 : 0.0;
 
186
    else if( strmatch(next, "lt"    ) ) d= d >  d2 ? 0.0 : 1.0;
 
187
    else if( strmatch(next, "lte"   ) ) d= d >= d2 ? 0.0 : 1.0;
121
188
    else if( strmatch(next, "eq"    ) ) d= d == d2 ? 1.0 : 0.0;
122
189
    else if( strmatch(next, "("     ) ) d= d;
123
190
//    else if( strmatch(next, "l1"    ) ) d= 1 + d2*(d - 1);
135
202
            }
136
203
        }
137
204
 
138
 
        av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next);
 
205
        *p->error = "unknown function";
139
206
        return NAN;
140
207
    }
141
208
 
142
209
    return d;
143
210
}
144
211
 
145
 
static double evalPow(Parser *p){
146
 
    int sign= (*p->s == '+') - (*p->s == '-');
147
 
    p->s += sign&1;
148
 
    return (sign|1) * evalPrimary(p);
 
212
static double evalPow(Parser *p, int *sign){
 
213
    *sign= (*p->s == '+') - (*p->s == '-');
 
214
    p->s += *sign&1;
 
215
    return evalPrimary(p);
149
216
}
150
217
 
151
218
static double evalFactor(Parser *p){
152
 
    double ret= evalPow(p);
 
219
    int sign, sign2;
 
220
    double ret, e;
 
221
    ret= evalPow(p, &sign);
153
222
    while(p->s[0]=='^'){
154
223
        p->s++;
155
 
        ret= pow(ret, evalPow(p));
 
224
        e= evalPow(p, &sign2);
 
225
        ret= pow(ret, (sign2|1) * e);
156
226
    }
157
 
    return ret;
 
227
    return (sign|1) * ret;
158
228
}
159
229
 
160
230
static double evalTerm(Parser *p){
182
252
    return ret;
183
253
}
184
254
 
185
 
double ff_eval(char *s, double *const_value, const char **const_name,
 
255
double ff_eval2(char *s, double *const_value, const char **const_name,
186
256
               double (**func1)(void *, double), const char **func1_name,
187
257
               double (**func2)(void *, double, double), char **func2_name,
188
 
               void *opaque){
 
258
               void *opaque, char **error){
189
259
    Parser p;
190
260
 
191
261
    p.stack_index=100;
197
267
    p.func2      = func2;
198
268
    p.func2_name = func2_name;
199
269
    p.opaque     = opaque;
 
270
    p.error= error;
200
271
 
201
272
    return evalExpression(&p);
202
273
}
203
274
 
 
275
#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
 
276
attribute_deprecated double ff_eval(char *s, double *const_value, const char **const_name,
 
277
               double (**func1)(void *, double), const char **func1_name,
 
278
               double (**func2)(void *, double, double), char **func2_name,
 
279
               void *opaque){
 
280
    char *error=NULL;
 
281
    double ret;
 
282
    ret = ff_eval2(s, const_value, const_name, func1, func1_name, func2, func2_name, opaque, &error);
 
283
    if (error)
 
284
        av_log(NULL, AV_LOG_ERROR, "Error evaluating \"%s\": %s\n", s, error);
 
285
    return ret;
 
286
}
 
287
#endif
 
288
 
204
289
#ifdef TEST
205
290
#undef printf
206
291
static double const_values[]={
216
301
main(){
217
302
    int i;
218
303
    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));
 
304
    printf("%f == 0.931322575\n", ff_eval("80G/80Gi", const_values, const_names, NULL, NULL, NULL, NULL, NULL));
219
305
 
220
306
    for(i=0; i<1050; i++){
221
307
        START_TIMER