summaryrefslogtreecommitdiffstats
path: root/include/interpolate.h
blob: da23315d48670c0ad7cf4a70e9dd0b772d71886e (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// Math for Game Programmers: Fast and Funky 1D Nonlinear Transformations
//   https://www.youtube.com/watch?v=mr5xkf6zSzk
//
// Thread safety: Safe for concurrent use (no shared state, pure functions).
// Macros: Namespaced INTERP_* variants are collision-safe. Legacy un-prefixed
//   names are provided via #ifndef guard — if your code already defines e.g.
//   "mix", the library will not override it.

#ifndef INTERPOLATE_H
#define INTERPOLATE_H

// Namespaced macros (safe from collisions). Use these in new code.
#ifndef INTERP_FLIP
#define INTERP_FLIP(x) (1.0 - (double)(x))
#endif
#ifndef INTERP_SCALE
#define INTERP_SCALE(a, t) ((double)(t) * (double)(a))
#endif
#ifndef INTERP_REVERSE_SCALE
#define INTERP_REVERSE_SCALE(a, t) ((1.0 - (double)(t)) * (double)(a))
#endif
#ifndef INTERP_MIX
#define INTERP_MIX(a, b, b_weight) ((double)(a) + (double)(b_weight) * ((double)(b) - (double)(a)))
#endif
#ifndef INTERP_CROSSFADE
#define INTERP_CROSSFADE(a, b, t) ((double)(a) + (double)(t) * ((double)(b) - (double)(a)))
#endif

#ifndef INTERP_SMOOTH_START_2
#define INTERP_SMOOTH_START_2(t) ((double)(t) * (double)(t))
#endif
#ifndef INTERP_SMOOTH_START_3
#define INTERP_SMOOTH_START_3(t) (INTERP_SMOOTH_START_2(t) * (double)(t))
#endif
#ifndef INTERP_SMOOTH_START_4
#define INTERP_SMOOTH_START_4(t) (INTERP_SMOOTH_START_3(t) * (double)(t))
#endif
#ifndef INTERP_SMOOTH_START_5
#define INTERP_SMOOTH_START_5(t) (INTERP_SMOOTH_START_4(t) * (double)(t))
#endif
#ifndef INTERP_SMOOTH_START_6
#define INTERP_SMOOTH_START_6(t) (INTERP_SMOOTH_START_5(t) * (double)(t))
#endif

#ifndef INTERP_SMOOTH_STOP_2
#define INTERP_SMOOTH_STOP_2(t) (INTERP_FLIP(INTERP_SMOOTH_START_2(INTERP_FLIP(t))))
#endif
#ifndef INTERP_SMOOTH_STOP_3
#define INTERP_SMOOTH_STOP_3(t) (INTERP_FLIP(INTERP_SMOOTH_START_3(INTERP_FLIP(t))))
#endif
#ifndef INTERP_SMOOTH_STOP_4
#define INTERP_SMOOTH_STOP_4(t) (INTERP_FLIP(INTERP_SMOOTH_START_4(INTERP_FLIP(t))))
#endif
#ifndef INTERP_SMOOTH_STOP_5
#define INTERP_SMOOTH_STOP_5(t) (INTERP_FLIP(INTERP_SMOOTH_START_5(INTERP_FLIP(t))))
#endif
#ifndef INTERP_SMOOTH_STOP_6
#define INTERP_SMOOTH_STOP_6(t) (INTERP_FLIP(INTERP_SMOOTH_START_6(INTERP_FLIP(t))))
#endif

#ifndef INTERP_SMOOTH_STEP_3
#define INTERP_SMOOTH_STEP_3(t) (INTERP_CROSSFADE(INTERP_SMOOTH_START_2(t), INTERP_SMOOTH_STOP_2(t), (double)(t)))
#endif

#ifndef INTERP_ARCH_2
#define INTERP_ARCH_2(t) (INTERP_SCALE(INTERP_FLIP(t), (double)(t)))
#endif
#ifndef INTERP_SMOOTH_START_ARCH_3
#define INTERP_SMOOTH_START_ARCH_3(t) (INTERP_SCALE(INTERP_ARCH_2(t), (double)(t)))
#endif
#ifndef INTERP_SMOOTH_STOP_ARCH_3
#define INTERP_SMOOTH_STOP_ARCH_3(t) (INTERP_REVERSE_SCALE(INTERP_ARCH_2(t), (double)(t)))
#endif

// Legacy macro names — alias to namespaced variants when not already defined by user.
#ifndef flip
#define flip(x) INTERP_FLIP(x)
#endif
#ifndef scale
#define scale(a, t) INTERP_SCALE(a, t)
#endif
#ifndef reverse_scale
#define reverse_scale(a, t) INTERP_REVERSE_SCALE(a, t)
#endif
#ifndef mix
#define mix(a, b, b_weight) INTERP_MIX(a, b, b_weight)
#endif
#ifndef crossfade
#define crossfade(a, b, t) INTERP_CROSSFADE(a, b, t)
#endif

#ifndef smooth_start_2
#define smooth_start_2(t) INTERP_SMOOTH_START_2(t)
#endif
#ifndef smooth_start_3
#define smooth_start_3(t) INTERP_SMOOTH_START_3(t)
#endif
#ifndef smooth_start_4
#define smooth_start_4(t) INTERP_SMOOTH_START_4(t)
#endif
#ifndef smooth_start_5
#define smooth_start_5(t) INTERP_SMOOTH_START_5(t)
#endif
#ifndef smooth_start_6
#define smooth_start_6(t) INTERP_SMOOTH_START_6(t)
#endif

#ifndef smooth_stop_2
#define smooth_stop_2(t) INTERP_SMOOTH_STOP_2(t)
#endif
#ifndef smooth_stop_3
#define smooth_stop_3(t) INTERP_SMOOTH_STOP_3(t)
#endif
#ifndef smooth_stop_4
#define smooth_stop_4(t) INTERP_SMOOTH_STOP_4(t)
#endif
#ifndef smooth_stop_5
#define smooth_stop_5(t) INTERP_SMOOTH_STOP_5(t)
#endif
#ifndef smooth_stop_6
#define smooth_stop_6(t) INTERP_SMOOTH_STOP_6(t)
#endif

#ifndef smooth_step_3
#define smooth_step_3(t) INTERP_SMOOTH_STEP_3(t)
#endif

#ifndef arch_2
#define arch_2(t) INTERP_ARCH_2(t)
#endif
#ifndef smooth_start_arch_3
#define smooth_start_arch_3(t) INTERP_SMOOTH_START_ARCH_3(t)
#endif
#ifndef smooth_stop_arch_3
#define smooth_stop_arch_3(t) INTERP_SMOOTH_STOP_ARCH_3(t)
#endif

/* Function wrappers for debuggability (use these instead of macros when debugging) */
#ifdef __cplusplus
extern "C" {
#endif

double interpolate_flip(double t);
double interpolate_scale(double a, double t);
double interpolate_reverse_scale(double a, double t);
double interpolate_mix(double a, double b, double b_weight);
double interpolate_crossfade(double a, double b, double t);
double interpolate_smooth_start_2(double t);
double interpolate_smooth_start_3(double t);
double interpolate_smooth_start_4(double t);
double interpolate_smooth_start_5(double t);
double interpolate_smooth_start_6(double t);
double interpolate_smooth_stop_2(double t);
double interpolate_smooth_stop_3(double t);
double interpolate_smooth_stop_4(double t);
double interpolate_smooth_stop_5(double t);
double interpolate_smooth_stop_6(double t);
double interpolate_smooth_step_3(double t);
double interpolate_arch_2(double t);
double interpolate_smooth_start_arch_3(double t);
double interpolate_smooth_stop_arch_3(double t);

#ifdef __cplusplus
}
#endif

#endif

#ifdef INTERPOLATE_IMPLEMENTATION
#ifndef INTERPOLATE_IMPLEMENTED
#define INTERPOLATE_IMPLEMENTED

double interpolate_flip(double t) { return flip(t); }
double interpolate_scale(double a, double t) { return scale(a, t); }
double interpolate_reverse_scale(double a, double t) { return reverse_scale(a, t); }
double interpolate_mix(double a, double b, double b_weight) { return mix(a, b, b_weight); }
double interpolate_crossfade(double a, double b, double t) { return crossfade(a, b, t); }
double interpolate_smooth_start_2(double t) { return smooth_start_2(t); }
double interpolate_smooth_start_3(double t) { return smooth_start_3(t); }
double interpolate_smooth_start_4(double t) { return smooth_start_4(t); }
double interpolate_smooth_start_5(double t) { return smooth_start_5(t); }
double interpolate_smooth_start_6(double t) { return smooth_start_6(t); }
double interpolate_smooth_stop_2(double t) { return smooth_stop_2(t); }
double interpolate_smooth_stop_3(double t) { return smooth_stop_3(t); }
double interpolate_smooth_stop_4(double t) { return smooth_stop_4(t); }
double interpolate_smooth_stop_5(double t) { return smooth_stop_5(t); }
double interpolate_smooth_stop_6(double t) { return smooth_stop_6(t); }
double interpolate_smooth_step_3(double t) { return smooth_step_3(t); }
double interpolate_arch_2(double t) { return arch_2(t); }
double interpolate_smooth_start_arch_3(double t) { return smooth_start_arch_3(t); }
double interpolate_smooth_stop_arch_3(double t) { return smooth_stop_arch_3(t); }

#endif /* INTERPOLATE_IMPLEMENTED */
#endif // INTERPOLATE_IMPLEMENTATION