From 96ecf29e8be977f51f351308ef2c7c492bb829aa Mon Sep 17 00:00:00 2001 From: Ethan Werner Date: Tue, 9 Jun 2026 01:17:41 +0400 Subject: refactor --- include/interpolate.h | 205 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 184 insertions(+), 21 deletions(-) (limited to 'include/interpolate.h') diff --git a/include/interpolate.h b/include/interpolate.h index 1f79405..da23315 100755 --- a/include/interpolate.h +++ b/include/interpolate.h @@ -1,31 +1,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 +#define INTERPOLATE_H -#define smooth_start_2( t ) ( t * t ) -#define smooth_start_3( t ) ( smooth_start_2( t ) * t ) -#define smooth_start_4( t ) ( smooth_start_3( t ) * t ) -#define smooth_start_5( t ) ( smooth_start_4( t ) * t ) -#define smooth_start_6( t ) ( smooth_start_5( t ) * t ) +// 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 -#define smooth_stop_2( t ) ( flip( smooth_start_2( flip( t ) ) ) ) -#define smooth_stop_3( t ) ( flip( smooth_start_3( flip( t ) ) ) ) -#define smooth_stop_4( t ) ( flip( smooth_start_4( flip( t ) ) ) ) -#define smooth_stop_5( t ) ( flip( smooth_start_5( flip( t ) ) ) ) -#define smooth_stop_6( t ) ( flip( smooth_start_6( flip( t ) ) ) ) +#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 -#define smooth_step_3( t ) ( crossfade( smooth_start_2( t ), smooth_stop_2( t ), t ) ) -#define mix( a, b, b_weight ) ( a + b_weight * ( b - a ) ) -#define crossfade( a, b, t ) ( a + t * ( b - a ) ) -#define scale( a, t ) ( t * a ) -#define reverse_scale( a, t ) ( ( 1 - t ) * a ) +#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 -#define arch_2( t ) ( scale( flip( t ), t ) ) -#define smooth_start_arch_3( t ) ( scale( arch_2( t ), t ) ) -#define smooth_stop_arch_3( t ) ( reverse_scale( arch_2( t ), t ) ) +#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 -#define flip( x ) ( 1 - x ) +#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 -#endif \ No newline at end of file +// 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 \ No newline at end of file -- cgit v1.3.1