From bd926b510b1a37977365182dbf13b13a1d7cdb38 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Fri, 23 May 2025 17:44:15 +0200 Subject: [PATCH] More vector operations, add/sub/scale --- linalg/main.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 200 insertions(+), 11 deletions(-) diff --git a/linalg/main.c b/linalg/main.c index 393bf1a..6d6ef38 100644 --- a/linalg/main.c +++ b/linalg/main.c @@ -3,6 +3,12 @@ #include #include +/* + * Simple linear algebra mat/vec operations + * + * TODO: Normalizations + */ + /** * @brief A 2×2 matrix stored in row-major order. * @@ -58,6 +64,68 @@ inline float vec3_dot(const Vec3 *a, const Vec3 *b); */ Vec3 vec3_cross(const Vec3 *a, const Vec3 *b); +/** + * @brief Subtracts one 3D vector from another. + * + * @param a Pointer to the minuend vector. + * @param b Pointer to the subtrahend vector. + * @return The resulting vector (a - b). + */ +Vec3 vec3_sub(const Vec3 *a, const Vec3 *b); + +/** + * @brief Adds two 3D vectors. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @return The resulting vector (a + b). + */ +Vec3 vec3_add(const Vec3 *a, const Vec3 *b); + +/** + * @brief Scales a 3D vector by a scalar value. + * + * @param a Pointer to the vector to scale. + * @param scalar The scalar value to multiply with the vector. + * @return The scaled vector (a * scalar). + */ +Vec3 vec3_scale(const Vec3 *a, const float scalar); + +/** + * @brief Computes the dot product of two 2D vectors. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @return The dot product (a • b). + */ +inline float vec2_dot(const Vec2 *a, const Vec2 *b); + +/** + * @brief Subtracts one 2D vector from another. + * + * @param a Pointer to the minuend vector. + * @param b Pointer to the subtrahend vector. + * @return The resulting vector (a - b). + */ +Vec2 vec2_sub(const Vec2 *a, const Vec2 *b); + +/** + * @brief Adds two 2D vectors. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @return The resulting vector (a + b). + */ +Vec2 vec2_add(const Vec2 *a, const Vec2 *b); + +/** + * @brief Scales a 2D vector by a scalar value. + * + * @param a Pointer to the vector to scale. + * @param scalar The scalar value to multiply with the vector. + * @return The scaled vector (a * scalar). + */ +Vec2 vec2_scale(const Vec2 *a, const float scalar); /** * @brief Computes the determinant of a 2×2 matrix. * @@ -112,6 +180,26 @@ bool mat2_approx_eq(const Mat2 *a, const Mat2 *b, float epsilon); */ bool mat3_approx_eq(const Mat3 *a, const Mat3 *b, float epsilon); +/** + * @brief Checks if two 3×3 vectors are approximately equal. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @param epsilon Tolerance for comparison. + * @return true if all elements are approximately equal within epsilon. + */ +bool vec3_approx_eq(const Vec3 *a, const Vec3 *b, float epsilon); + +/** + * @brief Checks if two 2x2 vectors are approximately equal. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @param epsilon Tolerance for comparison. + * @return true if all elements are approximately equal within epsilon. + */ +bool vec2_approx_eq(const Vec2 *a, const Vec2 *b, float epsilon); + #define MAT2_AT(m, row, col) ((m)->arr[(col) * 2 + (row)]) #define MAT3_AT(m, row, col) ((m)->arr[(col) * 3 + (row)]) @@ -134,14 +222,75 @@ float mat3_det(const Mat3 *m) { m02 * (m10 * m21 - m11 * m20); } -inline float vec3_dot(const struct Vec3 *a, const struct Vec3 *b) { +inline float vec3_dot(const Vec3 *a, const Vec3 *b) { return a->x * b->x + a->y * b->y + a->z * b->z; } -struct Vec3 vec3_cross(const struct Vec3 *a, const struct Vec3 *b) { - struct Vec3 res = {.x = a->y * b->z - a->z * b->y, - .y = a->x * b->z - a->z * b->x, - .z = a->x * b->y - a->y * b->x}; +Vec3 vec3_cross(const Vec3 *a, const Vec3 *b) { + Vec3 res = {.x = a->y * b->z - a->z * b->y, + .y = a->x * b->z - a->z * b->x, + .z = a->x * b->y - a->y * b->x}; + + return res; +} + +Vec3 vec3_sub(const Vec3 *a, const Vec3 *b) { + Vec3 res = { + .x = a->x - b->x, + .y = a->y - b->y, + .z = a->z - b->z, + }; + + return res; +} + +Vec3 vec3_add(const Vec3 *a, const Vec3 *b) { + Vec3 res = { + .x = a->x + b->x, + .y = a->y + b->y, + .z = a->z + b->z, + }; + + return res; +} + +Vec3 vec3_scale(const Vec3 *a, const float scalar) { + Vec3 res = { + .x = a->x * scalar, + .y = a->y * scalar, + .z = a->z * scalar, + }; + + return res; +} + +float vec2_dot(const Vec2 *a, const Vec2 *b) { + return a->x * b->x + a->y * b->y; +} + +Vec2 vec2_sub(const Vec2 *a, const Vec2 *b) { + Vec2 res = { + .x = a->x - b->x, + .y = a->y - b->y, + }; + + return res; +} + +Vec2 vec2_add(const Vec2 *a, const Vec2 *b) { + Vec2 res = { + .x = a->x + b->x, + .y = a->y + b->y, + }; + + return res; +} + +Vec2 vec2_scale(const Vec2 *a, const float scalar) { + Vec2 res = { + .x = a->x * scalar, + .y = a->y * scalar, + }; return res; } @@ -203,6 +352,15 @@ bool mat3_approx_eq(const Mat3 *a, const Mat3 *b, float epsilon) { return true; } +bool vec2_approx_eq(const Vec2 *a, const Vec2 *b, float epsilon) { + return (fabsf(a->x - b->x) <= epsilon) && (fabsf(a->y - b->y) <= epsilon); +} + +bool vec3_approx_eq(const Vec3 *a, const Vec3 *b, float epsilon) { + return (fabsf(a->x - b->x) <= epsilon) && (fabsf(a->y - b->y) <= epsilon) && + (fabsf(a->z - b->z) <= epsilon); +} + /* Implem end */ int main(void) { @@ -222,15 +380,46 @@ int main(void) { printf("Determinant: %f\n", d); } { - struct Vec3 a = {10, 10, 10}; - struct Vec3 b = {5, 5, 5}; - struct Vec3 c = vec3_cross(&a, &b); + /* Vector tests for addition, subtraction and multiplication (scale) */ + + /* Vec3 */ + + Vec3 a3 = {2, 2, 2}; + Vec3 b3 = {1, 1, 1}; + Vec3 c3_sub = vec3_sub(&a3, &b3); + Vec3 c3_add = vec3_add(&a3, &b3); + Vec3 m3 = vec3_scale(&a3, 1.5); + + Vec3 v3_expected_add = {3, 3, 3}; + + assert(vec3_approx_eq(&c3_sub, &b3, 0.01)); + assert(vec3_approx_eq(&c3_add, &v3_expected_add, 0.01)); + assert(vec3_approx_eq(&m3, &v3_expected_add, 0.01)); + + /* Vec2 */ + + Vec2 a2 = {2, 2}; + Vec2 b2 = {1, 1}; + Vec2 c2_sub = vec2_sub(&a2, &b2); + Vec2 c2_add = vec2_add(&a2, &b2); + Vec2 m2 = vec2_scale(&a2, 1.5); + + Vec2 v2_expected_add = {3, 3}; + + assert(vec2_approx_eq(&c2_sub, &b2, 0.01)); + assert(vec2_approx_eq(&c2_add, &v2_expected_add, 0.01)); + assert(vec2_approx_eq(&m2, &v2_expected_add, 0.01)); + } + { + Vec3 a = {10, 10, 10}; + Vec3 b = {5, 5, 5}; + Vec3 c = vec3_cross(&a, &b); printf("{ Vec3: %f, %f, %f }\n", c.x, c.y, c.z); } { - struct Vec3 a = {0, 1, 0}; - struct Vec3 b = {0, 0, 1}; - struct Vec3 c = vec3_cross(&a, &b); + Vec3 a = {0, 1, 0}; + Vec3 b = {0, 0, 1}; + Vec3 c = vec3_cross(&a, &b); printf("{ Vec3: %f, %f, %f }\n", c.x, c.y, c.z); }