From 749c09d78fa65b03d8820a877af70ce2389c3860 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Mon, 19 May 2025 14:56:25 +0200 Subject: [PATCH] Vec/Matrix linear algebra code things --- linalg/Makefile | 14 +++ linalg/main | Bin 0 -> 13000 bytes linalg/main.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 252 insertions(+) create mode 100644 linalg/Makefile create mode 100755 linalg/main create mode 100644 linalg/main.c diff --git a/linalg/Makefile b/linalg/Makefile new file mode 100644 index 0000000..40b00ed --- /dev/null +++ b/linalg/Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -Wall -O2 + +TARGET = main +SRC = main.c + +#LDFLAGS = + +$(TARGET): $(SRC) + @echo CC $@ + @$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +clean: + rm -f $(TARGET) diff --git a/linalg/main b/linalg/main new file mode 100755 index 0000000000000000000000000000000000000000..7f8b69aa4af4453765503e10d4f601f9ee346fbe GIT binary patch literal 13000 zcmeHNYj9h|6<*0oVnU*;Bm@iua$A(tVPZwLlVD6}uKbEjP2xI+U>bUnE!oyomV_RV z00mQ*hkL+AieFf{=RHKah8(!q3+jx*t5Ffb`FsNdPUN0x7# z^g*Y;yq?{&d-i< zWN(k`6oP3nj>dTMBFoIl3d;^tuNq&uqKu;^;Yu&IaHT#A$8=N;h$+W~+@M@W0g}|1 zM!m8n1XGfwM3k~|4z-9H)2VEMuc+N#zryt^98+D%Gi7^Qk7dIDjlEWd8(M5B9$IY3 z3e%Xy7EIaRH-V#g{=12nRhzPRy7?AfO=DLfNY0Ddg z0Jg#9pVYRyTw41aH?(ML=KOpi$h{$W5gf?5f&(YL+1EdW5e?l37Qn;(G~RImfvF}5 zd;;M3@h{-L_WmmeE+R>qfNrh)dE}?ZUn=e*z>@$_uM`{qHM%Qvn1J449v{t7<-5&; zFMpdxH*j>KwY{-2SNUA<*=L0d)3Nk0UThytjf&)lr?0 zlUm0yo};DzW|}PrBKHosY6z`qvLsPwM2vW&;xKdpe=IB){($q9ef!Dqt1gxEdp4+N3RL)N_e*( z5O_YY+;`pZ=J=zZ$!8{apoE{U;J`2pUtj;x_)pOny!=G=tpoGX85nrR5#041*LVu- zz`*Av*~h+hLtr~}_tWau$`2tdn#V=6?wX5dx^_N2(+6)^s-9&}c1%9LK;ZeW%oR^h z_mIRFJrmPZy?>Ua>Vm>+L8+Qrwa_PMP0RP{v^ObvH=AZ7FdKo{2+T%cHUhH|_+La| zO)T2Ee(joAxFQyfXLnTWs99gJeyuN^@Ks6mv{C2$pV*_b)8ZKbq-!Sr%G2=a%r}$# zX7F|7Q&KXUNej~qrPGmA#_SG7V`yQJU1mBH0;ew&jf-R|8qahKV$)F9i%l)fb@gVI zugbTsP_JGKWKUlru8=0#a^gfte>4tC4sa?!J+g&O`vp;Ka!SNyiub!8K7=7SMZM}j zvc`}#8W-yz##j-5+Wm&#pl&e_SshhnyR?W;MjKGCo1tVfmDpiMZYp2d zSG`(a*|%Ev`}~!wq!8J_;pI-YWzqhP)7#XVV4mT)u;hvuI17+RC-V7yp#Bf?`P~Rs z67+V^)(`Xf`@ru9eHgTLGM_&Jx)1anQ2isEn;~~2=sBSJ$N79YXg_E>Xbx1KxFM^q zJ%r=dHsRReaa_1yUg;2IXg=xgDF>UhHbuic5ApoSZ-U2j=!xWL0l$>aL6_u3Yna$ z&HW@x`l(HLO0=Gf*SciR7PAqUjlgUKW+N~gf!PSmMqoAqUn&B*Ifld!Da!jXI?GU^ z{WqlzC5EI6Wr;mtsnwSIK=Al?&BMC@5)$QtvLs?C1W zUY8Q@XW2e}d6MHXlswKovdwYD@j$kHs^8M`|10@-XS>Cl)%@P0=tGK<+@|{aTD=^* z@>P1}I-lQHsaN@{*7?^~*68JJk+2>NWmHFnf0a$TvLIcxZkjYYDsVmwTwA*~Sy@$6 zBigR5O=aWpXuL=7>FTmu5_Q+shT`!=XEZ)z_oi*N{vDTv*ZbG4uhM;=5Nv9x^`D`8QvfPjn`_sKt&O#Q5#5Sn znhVi*Gy{9mimFSMsyap>pJ{wOyS9Fe|gVd&g*HIm+ zEPTT;S3TpjhV3#-RUgxtWcVG>rq;$xGW=e6SiK)+lF^l|ku&)7V})lrlOFD4I+G0h zy6p@;v#*aRn-sp&C4^PD#0PnMKiPKRhRXiE#NyM)(|gkiO*!Qkzeg{TdfbA3&Zorp z3zwrlliddJNe{=AFqE2*iQlSXESV@e6rbPs%%_)>isR5 zD1M17{kQ4=m6Tsn_vjdDE)j-^n=sL?^W`Kk`F5bzXhNCvBx0? zzRpe*(LaH|$mtd*ZU5KaB))Kq3B`9Q%n9%pV}|$5GbD%BC8bZm_h22;cN4|wGm>|@ zgh$1hpNq$po-vmtzfysg;2%BdvBz^c_+(codAcv8MBi^Ma+aN9*RSL~YTm0Yaj}v3 zPG@0Xq}W1qr81Si1l>G$M$Js9XX=`iZc7ufFuGdX8r$1D%%*EL*S9xs*=(9VKjAtf zJ&;L=a3qCV8kewUrqAq(CE^jf$_^*Yo>-zY6f?t_L@I5DvO7dqqAwZ4b!`|LW|T0y z@gK(wrBb1tW+a|T?G)XqP+!ChXZ!kg0#ej6>3`ESQTP;zhvjIR+5%TMnvI(qOjDQ* z9h(DJH`fD>O@Y}MG_BrXLz^%+wQQ*iw3u6(nzlB!o9%(RmPR1#H}3{twBvGp`USGp z3`a78Ztx3obRiGHDzh((i~LA9lnDtrHg$(@7p%4fi|_xZiQJ3}ZL=$tNXy7Vn{~Ml zPp94VBc|zu*&B+7V-aCCZ-G=e8aK1)NZ4{z{(=C9;+WTP%#{DbLzxI^!~b+M83oMj zOsAE4`KyCzwqISZVkyT|xIGtg4)C%~@9fKjIzclji}rF&Ze)7mSzl*1ieGD@Vd0~B z6TVDj2TGc5;$ZP4g^%QVL+M`O3-63Wr$sXX7HGN*+l1;dB}LYWhyH%6t&u3ixf(JpE1LS z3SLQKu43?>X@fe5@cD@4?f6|b{Ef=~jS6otP*J&$L!Ieb)Qj!s6h5c$hiwK8rH4ta z4bS_z-L%0$T4<3%X;UW*^pJgypYRX|Njb>pKZ|L}a-C=p`4gOx7_Te5Zo?~g3g<}H z(S{102^nuFyrJ+zN|4TN!K z6rZQrF3T~ceHfh~xy|QDL*f0(nB9NH7I&aRbHaE&wmW08AirVpi0KXW|=K=n%TDRft{vSp^zK)e^kVN@jg}+<2 z+v7IVw}8=#@P&Ole}7I&ixT6Qo +#include +#include +#include + +/** + * @brief A 2×2 matrix stored in row-major order. + * + * The elements are laid out as: + * [ arr[0] arr[1] ] + * [ arr[2] arr[3] ] + */ +typedef struct Mat2 { + float arr[4]; +} Mat2; + +/** + * @brief A 3×3 matrix stored in row-major order. + * + * The elements are laid out as: + * [ arr[0] arr[1] arr[2] ] + * [ arr[3] arr[4] arr[5] ] + * [ arr[6] arr[7] arr[8] ] + */ +typedef struct Mat3 { + float arr[9]; +} Mat3; + +/** + * @brief A 2D vector with x and y components. + */ +typedef struct Vec2 { + float x, y; +} Vec2; + +/** + * @brief A 3D vector with x, y, and z components. + */ +typedef struct Vec3 { + float x, y, z; +} Vec3; + +/** + * @brief Computes the dot product of two 3D vectors. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @return The dot product (a • b). + */ +inline float vec3_dot(const Vec3 *a, const Vec3 *b); + +/** + * @brief Computes the cross product of two 3D vectors. + * + * @param a Pointer to the first vector. + * @param b Pointer to the second vector. + * @return The cross product vector (a × b). + */ +Vec3 vec3_cross(const Vec3 *a, const Vec3 *b); + +/** + * @brief Computes the determinant of a 2×2 matrix. + * + * @param m Pointer to the matrix. + * @return The determinant of the matrix. + */ +float mat2_det(const Mat2 *m); + +/** + * @brief Computes the determinant of a 3×3 matrix (row-major order). + * + * @param m Pointer to the matrix. + * @return The determinant of the matrix. + */ +float mat3_det2(const Mat3 *m); + +/** + * @brief Multiplies two 2×2 matrices (row-major order). + * + * @param m1 Pointer to the first matrix. + * @param m2 Pointer to the second matrix. + * @return The resulting matrix product (m1 × m2). + */ +Mat2 mat2_mul(const Mat2 *m1, const Mat2 *m2); + +/** + * @brief Multiplies two 3×3 matrices (row-major order). + * + * @param m1 Pointer to the first matrix. + * @param m2 Pointer to the second matrix. + * @return The resulting matrix product (m1 × m2). + */ +Mat3 mat3_mul(const Mat3 *m1, const Mat3 *m2); + +/** + * @brief Checks if two 2×2 matrices are approximately equal. + * + * @param a Pointer to the first matrix. + * @param b Pointer to the second matrix. + * @param epsilon Tolerance for comparison. + * @return true if all elements are approximately equal within epsilon. + */ +bool mat2_approx_eq(const Mat2 *a, const Mat2 *b, float epsilon); + +/** + * @brief Checks if two 3×3 matrices are approximately equal. + * + * @param a Pointer to the first matrix. + * @param b Pointer to the second matrix. + * @param epsilon Tolerance for comparison. + * @return true if all elements are approximately equal within epsilon. + */ +bool mat3_approx_eq(const Mat3 *a, const Mat3 *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)]) + +/* Header end... */ + +float mat3_det(const Mat3 *m) { + float m00 = MAT3_AT(m, 0, 0); + float m01 = MAT3_AT(m, 0, 1); + float m02 = MAT3_AT(m, 0, 2); + + float m10 = MAT3_AT(m, 1, 0); + float m11 = MAT3_AT(m, 1, 1); + float m12 = MAT3_AT(m, 1, 2); + + float m20 = MAT3_AT(m, 2, 0); + float m21 = MAT3_AT(m, 2, 1); + float m22 = MAT3_AT(m, 2, 2); + + return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + + m02 * (m10 * m21 - m11 * m20); +} + +inline float vec3_dot(const struct Vec3 *a, const struct 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}; + + return res; +} + +Mat2 mat2_mul(const Mat2 *m1, const Mat2 *m2) { + Mat2 m3 = {.arr = { + MAT2_AT(m1, 0, 0) * MAT2_AT(m2, 0, 0) + + MAT2_AT(m1, 0, 1) * MAT2_AT(m2, 1, 0), + MAT2_AT(m1, 1, 0) * MAT2_AT(m2, 0, 0) + + MAT2_AT(m1, 1, 1) * MAT2_AT(m2, 1, 0), + MAT2_AT(m1, 0, 0) * MAT2_AT(m2, 0, 1) + + MAT2_AT(m1, 0, 1) * MAT2_AT(m2, 1, 1), + MAT2_AT(m1, 1, 0) * MAT2_AT(m2, 0, 1) + + MAT2_AT(m1, 1, 1) * MAT2_AT(m2, 1, 1), + }}; + + return m3; +} + +Mat3 mat3_mul(const Mat3 *m1, const Mat3 *m2) { + Mat3 m3; + + for (int col = 0; col < 3; ++col) { + for (int row = 0; row < 3; ++row) { + float sum = 0.0f; + for (int k = 0; k < 3; ++k) { + sum += MAT3_AT(m1, row, k) * MAT3_AT(m2, k, col); + } + m3.arr[col * 3 + row] = sum; + } + } + + return m3; +} + +void mat3_print(const Mat3 *m) { + for (int row = 0; row < 3; ++row) { + printf("| "); + for (int col = 0; col < 3; ++col) { + printf("%8.3f ", MAT3_AT(m, row, col)); + } + printf("|\n"); + } +} + +bool mat2_approx_eq(const Mat2 *a, const Mat2 *b, float epsilon) { + for (int i = 0; i < 4; ++i) { + if (fabsf(a->arr[i] - b->arr[i]) > epsilon) + return false; + } + return true; +} + +bool mat3_approx_eq(const Mat3 *a, const Mat3 *b, float epsilon) { + for (int i = 0; i < 9; ++i) { + if (fabsf(a->arr[i] - b->arr[i]) > epsilon) + return false; + } + return true; +} + +/* Implem end */ + +int main(void) { + { + Mat3 m = {{1, 0, 0, 0, 1, 0, 0, 0, 1}}; + + Mat3 m3 = mat3_mul(&m, &m); + assert(mat3_approx_eq(&m3, &m, 0.01)); + } + { + Mat3 m = {{1, 0, 0, 0, 1, 0, 0, 0, 1}}; + float d = mat3_det(&m); + printf("Determinant: %f\n", d); + + MAT3_AT(&m, 0, 0) = 2; + d = mat3_det(&m); + printf("Determinant: %f\n", d); + } + { + struct Vec3 a = {10, 10, 10}; + struct Vec3 b = {5, 5, 5}; + struct 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); + printf("{ Vec3: %f, %f, %f }\n", c.x, c.y, c.z); + } + + return 0; +}