Commit Diff


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);