From c147bf2ce5819d33d20bd041fd215e9d41b1dfef Mon Sep 17 00:00:00 2001 From: Shreyash Date: Fri, 29 Aug 2025 23:43:24 +0530 Subject: [PATCH 1/2] chore: add build to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 600d2d3..6a8bc10 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -.vscode \ No newline at end of file +.vscode +build \ No newline at end of file From 5c32221ce1e9200307e878bea4f48dd02a208068 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Fri, 29 Aug 2025 23:43:46 +0530 Subject: [PATCH 2/2] feat: add matrix operations --- nn/src/linalg/io.c | 4 + nn/src/linalg/operations.c | 163 +++++++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/nn/src/linalg/io.c b/nn/src/linalg/io.c index 258f881..14f0071 100644 --- a/nn/src/linalg/io.c +++ b/nn/src/linalg/io.c @@ -7,6 +7,10 @@ #include "linalg.h" #include "utils.h" +//============================ +// Functions for Matrix IO +//============================ + Matrix* read_matrix(const char* filename) { LOG_INFO("Attempting to load matrix from file: %s", filename); diff --git a/nn/src/linalg/operations.c b/nn/src/linalg/operations.c index e69de29..9a89ae6 100644 --- a/nn/src/linalg/operations.c +++ b/nn/src/linalg/operations.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include + +#include "linalg.h" +#include "utils.h" + +//============================ +// Functions for Matrix Operations +//============================ + +Matrix* identity_matrix(int n) { + LOG_INFO("Creating a %dx%d identity matrix.", n, n); + ASSERT(n > 0, "Matrix size must be greater than 0."); + Matrix* m = create_matrix(n, n); + // Use memset to efficiently initialize all elements to 0 + memset(m->matrix_data, 0, n * n * sizeof(double)); + for (int i = 0; i < n; i++) { + m->matrix_data[i * n + i] = 1.0; + } + LOG_INFO("Identity matrix created successfully."); + return m; +} + +Matrix* add_matrix(Matrix* a, Matrix* b) { + ASSERT(a != NULL && b != NULL, "Input matrices cannot be NULL."); + ASSERT(a->rows == b->rows && a->cols == b->cols, + "Matrices must have the same dimensions for addition."); + + LOG_INFO("Adding two %dx%d matrices.", a->rows, a->cols); + Matrix* result = create_matrix(a->rows, a->cols); + int total_elements = a->rows * a->cols; + + for (int i = 0; i < total_elements; i++) { + result->matrix_data[i] = a->matrix_data[i] + b->matrix_data[i]; + } + + LOG_INFO("Matrix addition complete."); + return result; +} + +Matrix* subtract_matrix(Matrix* a, Matrix* b) { + ASSERT(a != NULL && b != NULL, "Input matrices cannot be NULL."); + ASSERT(a->rows == b->rows && a->cols == b->cols, + "Matrices must have the same dimensions for subtraction."); + + LOG_INFO("Subtracting two %dx%d matrices.", a->rows, a->cols); + Matrix* result = create_matrix(a->rows, a->cols); + int total_elements = a->rows * a->cols; + + for (int i = 0; i < total_elements; i++) { + result->matrix_data[i] = a->matrix_data[i] - b->matrix_data[i]; + } + + LOG_INFO("Matrix subtraction complete."); + return result; +} + +Matrix* multiply_matrix(Matrix* a, Matrix* b) { + ASSERT(a != NULL && b != NULL, "Input matrices cannot be NULL."); + ASSERT(a->rows == b->rows && a->cols == b->cols, + "Matrices must have the same dimensions for element-wise " + "multiplication."); + + LOG_INFO("Multiplying two %dx%d matrices element-wise.", a->rows, a->cols); + Matrix* result = create_matrix(a->rows, a->cols); + int total_elements = a->rows * a->cols; + + for (int i = 0; i < total_elements; i++) { + result->matrix_data[i] = a->matrix_data[i] * b->matrix_data[i]; + } + + LOG_INFO("Element-wise matrix multiplication complete."); + return result; +} + +Matrix* apply_onto_matrix(double (*func)(double), Matrix* m) { + ASSERT(m != NULL, "Input matrix cannot be NULL."); + LOG_INFO("Applying a function to each element of a %dx%d matrix.", m->rows, + m->cols); + Matrix* result = create_matrix(m->rows, m->cols); + int total_elements = m->rows * m->cols; + + for (int i = 0; i < total_elements; i++) { + result->matrix_data[i] = func(m->matrix_data[i]); + } + + LOG_INFO("Function application to matrix complete."); + return result; +} + +Matrix* add_scalar_to_matrix(Matrix* m, double n) { + ASSERT(m != NULL, "Input matrix cannot be NULL."); + LOG_INFO("Adding scalar %.2f to a %dx%d matrix.", n, m->rows, m->cols); + Matrix* result = create_matrix(m->rows, m->cols); + int total_elements = m->rows * m->cols; + + for (int i = 0; i < total_elements; i++) { + result->matrix_data[i] = m->matrix_data[i] + n; + } + + LOG_INFO("Scalar addition complete."); + return result; +} + +Matrix* dot_matrix(Matrix* a, Matrix* b) { + ASSERT(a != NULL && b != NULL, "Input matrices cannot be NULL."); + ASSERT(a->cols == b->rows, + "The number of columns in the first matrix must equal the number of " + "rows in the second matrix for dot product."); + + LOG_INFO("Performing dot product on a %dx%d and a %dx%d matrix.", a->rows, + a->cols, b->rows, b->cols); + Matrix* result = create_matrix(a->rows, b->cols); + + for (int i = 0; i < a->rows; i++) { + for (int j = 0; j < b->cols; j++) { + double sum = 0; + for (int k = 0; k < a->cols; k++) { + sum += + a->matrix_data[i * a->cols + k] * b->matrix_data[k * b->cols + j]; + } + result->matrix_data[i * result->cols + j] = sum; + } + } + + LOG_INFO("Matrix dot product complete. Resulting matrix is %dx%d.", + result->rows, result->cols); + return result; +} + +Matrix* transpose_matrix(Matrix* m) { + ASSERT(m != NULL, "Input matrix cannot be NULL."); + LOG_INFO("Transposing a %dx%d matrix.", m->rows, m->cols); + Matrix* result = create_matrix(m->cols, m->rows); + + for (int i = 0; i < m->rows; i++) { + for (int j = 0; j < m->cols; j++) { + result->matrix_data[j * result->cols + i] = + m->matrix_data[i * m->cols + j]; + } + } + + LOG_INFO("Matrix transpose complete. Resulting matrix is %dx%d.", + result->rows, result->cols); + return result; +} + +Matrix* scale_matrix(double n, Matrix* m) { + ASSERT(m != NULL, "Input matrix cannot be NULL."); + LOG_INFO("Scaling a %dx%d matrix by %.2f.", m->rows, m->cols, n); + Matrix* result = create_matrix(m->rows, m->cols); + int total_elements = m->rows * m->cols; + + for (int i = 0; i < total_elements; i++) { + result->matrix_data[i] = m->matrix_data[i] * n; + } + + LOG_INFO("Matrix scaling complete."); + return result; +}