commit afccd2672f33f8db43d1d7290f7c0c25daaecef2 from: Evan Burkey date: Sat Mar 14 06:25:29 2026 UTC add abs_int, gcd, lcm, lerp, isqrt to math module commit - ea03bfa556eeaf3f10a455e6b5f529257bee028b commit + afccd2672f33f8db43d1d7290f7c0c25daaecef2 blob - 09f75a4eebbfe103cfd27d9f4b491e10830143f8 blob + 5267d993e8cabdd120bb33ff40697062085caf05 --- include/lfmath.h +++ include/lfmath.h @@ -13,8 +13,18 @@ int clamp_int(int i, int low, int high); int binstr_to_int(const char *s); +int abs_int(int i); + int is_power_of_two(int i); +int gcd(int a, int b); + +int lcm(int a, int b); + +float lerp(float a, float b, float t); + +int isqrt(int n); + Point *bresenham(int x0, int y0, int x1, int y1, size_t *sz); Point *bresenham_p(Point p1, Point p2, size_t *sz); blob - 5659ee6ca791e2ed0df101b495a7236946c2a812 blob + 08fed2d2db0c250cc94df7548df5cff989f536f2 --- src/math.c +++ src/math.c @@ -77,6 +77,48 @@ Point *bresenham_p(Point p1, Point p2, size_t *sz) { return bresenham(p1.x, p1.y, p2.x, p2.y, sz); } +int abs_int(int i) { + return i < 0 ? -i : i; +} + int is_power_of_two(int i) { return i > 0 && (i & (i - 1)) == 0; } + +int gcd(int a, int b) { + a = abs_int(a); + b = abs_int(b); + while (b) { + int tmp = b; + b = a % b; + a = tmp; + } + return a; +} + +int lcm(int a, int b) { + if (a == 0 || b == 0) { + return 0; + } + return abs_int(a / gcd(a, b) * b); +} + +float lerp(float a, float b, float t) { + return a + t * (b - a); +} + +int isqrt(int n) { + if (n < 0) { + return -1; + } + if (n < 2) { + return n; + } + int x = n; + int y = (x + 1) / 2; + while (y < x) { + x = y; + y = (x + n / x) / 2; + } + return x; +} blob - 780eca704baf4f47eec03ef622bf50095d48d0bb blob + 50629b4a980d0cab64d560728ae38875b324dfb6 --- tests/test_math.c +++ tests/test_math.c @@ -18,6 +18,39 @@ int main() { i = clamp_int(i, 2, 5); ASSERT_EQ(i, 5); + /* abs_int */ + ASSERT_EQ(abs_int(5), 5); + ASSERT_EQ(abs_int(-5), 5); + ASSERT_EQ(abs_int(0), 0); + + /* gcd */ + ASSERT_EQ(gcd(12, 8), 4); + ASSERT_EQ(gcd(7, 13), 1); + ASSERT_EQ(gcd(0, 5), 5); + ASSERT_EQ(gcd(5, 0), 5); + ASSERT_EQ(gcd(-12, 8), 4); + ASSERT_EQ(gcd(-6, -9), 3); + + /* lcm */ + ASSERT_EQ(lcm(4, 6), 12); + ASSERT_EQ(lcm(7, 13), 91); + ASSERT_EQ(lcm(1, 5), 5); + ASSERT_EQ(lcm(0, 5), 0); + + /* lerp */ + ASSERT_TRUE(lerp(0.0f, 10.0f, 0.0f) == 0.0f); + ASSERT_TRUE(lerp(0.0f, 10.0f, 1.0f) == 10.0f); + ASSERT_TRUE(lerp(0.0f, 10.0f, 0.5f) == 5.0f); + ASSERT_TRUE(lerp(2.0f, 4.0f, 0.25f) == 2.5f); + + /* isqrt */ + ASSERT_EQ(isqrt(0), 0); + ASSERT_EQ(isqrt(1), 1); + ASSERT_EQ(isqrt(25), 5); + ASSERT_EQ(isqrt(26), 5); + ASSERT_EQ(isqrt(100), 10); + ASSERT_EQ(isqrt(-1), -1); + size_t sz = 0; Point *line = bresenham(0, 0, 2, 5, &sz); ASSERT_TRUE(sz > 0);