~ubuntu-branches/ubuntu/hardy/avidemux/hardy

« back to all changes in this revision

Viewing changes to avidemux/ADM_lavcodec/eval.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T Chen
  • Date: 2006-12-15 17:13:20 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20061215171320-w79pvpehxx2fr217
Tags: 1:2.3.0-0.0ubuntu1
* Merge from debian-multimedia.org, remaining Ubuntu change:
  - desktop file,
  - no support for ccache and make -j.
* Closes Ubuntu: #69614.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
19
 *
 
20
 */
 
21
 
 
22
/**
 
23
 * @file eval.c
 
24
 * simple arithmetic expression evaluator.
 
25
 *
 
26
 * see http://joe.hotchkiss.com/programming/eval/eval.html
 
27
 */
 
28
 
 
29
#include "avcodec.h"
 
30
#include "mpegvideo.h"
 
31
 
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include <math.h>
 
36
 
 
37
#ifndef NAN
 
38
  #define NAN 0
 
39
#endif
 
40
 
 
41
#ifndef M_PI
 
42
#define M_PI 3.14159265358979323846
 
43
#endif
 
44
 
 
45
typedef struct Parser{
 
46
    int stack_index;
 
47
    char *s;
 
48
    double *const_value;
 
49
    const char **const_name;          // NULL terminated
 
50
    double (**func1)(void *, double a); // NULL terminated
 
51
    const char **func1_name;          // NULL terminated
 
52
    double (**func2)(void *, double a, double b); // NULL terminated
 
53
    char **func2_name;          // NULL terminated
 
54
    void *opaque;
 
55
} Parser;
 
56
 
 
57
static double evalExpression(Parser *p);
 
58
 
 
59
static int strmatch(const char *s, const char *prefix){
 
60
    int i;
 
61
    for(i=0; prefix[i]; i++){
 
62
        if(prefix[i] != s[i]) return 0;
 
63
    }
 
64
    return 1;
 
65
}
 
66
 
 
67
static double evalPrimary(Parser *p){
 
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;
 
76
        return d;
 
77
    }
 
78
 
 
79
    /* named constants */
 
80
    for(i=0; p->const_name && p->const_name[i]; i++){
 
81
        if(strmatch(p->s, p->const_name[i])){
 
82
            p->s+= strlen(p->const_name[i]);
 
83
            return p->const_value[i];
 
84
        }
 
85
    }
 
86
 
 
87
    p->s= strchr(p->s, '(');
 
88
    if(p->s==NULL){
 
89
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ( in \"%s\"\n", next);
 
90
        return NAN;
 
91
    }
 
92
    p->s++; // "("
 
93
    d= evalExpression(p);
 
94
    if(p->s[0]== ','){
 
95
        p->s++; // ","
 
96
        d2= evalExpression(p);
 
97
    }
 
98
    if(p->s[0] != ')'){
 
99
        av_log(NULL, AV_LOG_ERROR, "Parser: missing ) in \"%s\"\n", next);
 
100
        return NAN;
 
101
    }
 
102
    p->s++; // ")"
 
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);
 
114
    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;
 
121
    else if( strmatch(next, "eq"    ) ) d= d == d2 ? 1.0 : 0.0;
 
122
    else if( strmatch(next, "("     ) ) d= d;
 
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])){
 
128
                return p->func1[i](p->opaque, d);
 
129
            }
 
130
        }
 
131
 
 
132
        for(i=0; p->func2_name && p->func2_name[i]; i++){
 
133
            if(strmatch(next, p->func2_name[i])){
 
134
                return p->func2[i](p->opaque, d, d2);
 
135
            }
 
136
        }
 
137
 
 
138
        av_log(NULL, AV_LOG_ERROR, "Parser: unknown function in \"%s\"\n", next);
 
139
        return NAN;
 
140
    }
 
141
 
 
142
    return d;
 
143
}
 
144
 
 
145
static double evalPow(Parser *p){
 
146
    int sign= (*p->s == '+') - (*p->s == '-');
 
147
    p->s += sign&1;
 
148
    return (sign|1) * evalPrimary(p);
 
149
}
 
150
 
 
151
static double evalFactor(Parser *p){
 
152
    double ret= evalPow(p);
 
153
    while(p->s[0]=='^'){
 
154
        p->s++;
 
155
        ret= pow(ret, evalPow(p));
 
156
    }
 
157
    return ret;
 
158
}
 
159
 
 
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);
 
165
    }
 
166
    return ret;
 
167
}
 
168
 
 
169
static double evalExpression(Parser *p){
 
170
    double ret= 0;
 
171
 
 
172
    if(p->stack_index <= 0) //protect against stack overflows
 
173
        return NAN;
 
174
    p->stack_index--;
 
175
 
 
176
    do{
 
177
        ret += evalTerm(p);
 
178
    }while(*p->s == '+' || *p->s == '-');
 
179
 
 
180
    p->stack_index++;
 
181
 
 
182
    return ret;
 
183
}
 
184
 
 
185
double ff_eval(char *s, double *const_value, const char **const_name,
 
186
               double (**func1)(void *, double), const char **func1_name,
 
187
               double (**func2)(void *, double, double), char **func2_name,
 
188
               void *opaque){
 
189
    Parser p;
 
190
 
 
191
    p.stack_index=100;
 
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
 
 
201
    return evalExpression(&p);
 
202
}
 
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(){
 
217
    int i;
 
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));
 
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
    }
 
225
}
 
226
#endif