blob: a8082320bd5efb1174a48c9104b537bbe7442df2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#include <math.h>
#include "expr.h"
double expr_eval(struct expr *expr, double time)
{
switch (expr->type) {
case EXPR_NUMBER: return expr->number;
case EXPR_TIME: return time;
case EXPR_OP: {
size_t n_args = expr->op.args.len;
double args[n_args];
for (size_t i = 0; i < n_args; i++)
args[i] = expr_eval(&expr->op.args.ptr[i], time);
double accum;
switch (expr->op.type) {
case OP_ADD:
accum = 0.0;
for (size_t i = 0; i < n_args; i++)
accum += args[i];
return accum;
case OP_SUB:
if (n_args == 1) return -args[0];
return args[0] - args[1];
case OP_MUL:
accum = 1.0;
for (size_t i = 0; i < n_args; i++)
accum *= args[i];
return accum;
case OP_DIV:
if (n_args == 1) return 1.0 / args[0];
return args[0] / args[1];
case OP_MOD:
return fmod(args[0], args[1]);
case OP_MIN:
for (size_t i = 0; i < n_args; i++)
if (i == 0 || args[i] < accum)
accum = args[i];
return accum;
case OP_MAX:
for (size_t i = 0; i < n_args; i++)
if (i == 0 || args[i] > accum)
accum = args[i];
return accum;
case OP_CLAMP:
if (args[0] < args[1]) return args[1];
if (args[0] > args[2]) return args[2];
return args[0];
case OP_MIX:
return args[0] + (args[1] - args[0]) * args[2];
case OP_ABS:
return fabs(args[0]);
default: break; // unreachable
}
}
}
return 0.0;
}
void expr_free(struct expr *expr)
{
if (expr->type == EXPR_OP) {
for (size_t i = 0; i < expr->op.args.len; i++)
expr_free(&expr->op.args.ptr[i]);
free(expr->op.args.ptr);
}
}
void expr_copy(struct expr *dst, struct expr *src)
{
*dst = *src;
if (src->type == EXPR_OP)
array_dup(&dst->op.args, &src->op.args);
}
|