From 29e9250356c1f64c132c3ae687d46dafd2bf2485 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Mon, 25 Aug 2025 22:48:24 +0530 Subject: [PATCH 1/5] feat: add clang format specifications and ci for code analysis and linting checks --- .clang-format | 3 +++ .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 .clang-format create mode 100644 .github/workflows/ci.yml diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..41c631f --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +# .clang-format +BasedOnStyle: Google +IndentWidth: 4 \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..82163eb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +# .github/workflows/ci.yml +name: C/C++ CI + +on: + pull_request: + branches: + - main + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Install build tools and linter + run: sudo apt-get update && sudo apt-get install -y clang-format cppcheck + + - name: Check code formatting + run: | + find . -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google --dry-run --Werror-on-style-issue + + - name: Run static code analysis + run: | + cppcheck --enable=all --suppress=missingIncludeSystem --inconclusive --error-exitcode=1 . \ No newline at end of file From 28e03f572160f356b3fae0304e500edc5a2e3c82 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Mon, 25 Aug 2025 23:07:26 +0530 Subject: [PATCH 2/5] chore: update actions to support more versions of clang-format --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82163eb..0c72bc1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,13 @@ jobs: - name: Check code formatting run: | - find . -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google --dry-run --Werror-on-style-issue + # Create a copy of the source code + cp -r . temp_repo + # Format the copied source code + find temp_repo -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google + # Compare the original with the formatted code + diff -u temp_repo . + # If the diff command finds any differences, it will exit with a non-zero code and fail the workflow. - name: Run static code analysis run: | From 4d26219617b65a4e41afa969f74dff785585ee2f Mon Sep 17 00:00:00 2001 From: Shreyash Date: Mon, 25 Aug 2025 23:10:39 +0530 Subject: [PATCH 3/5] chore: update actions to prevent copy errors during format check --- .github/workflows/ci.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c72bc1..96ba291 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,14 +17,17 @@ jobs: - name: Check code formatting run: | - # Create a copy of the source code - cp -r . temp_repo - # Format the copied source code - find temp_repo -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google + # Create a temporary directory outside the current directory + mkdir -p ../temp_repo + # Copy all files into the temporary directory + cp -r . ../temp_repo + + # Now, format the copied source code + find ../temp_repo -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google + # Compare the original with the formatted code - diff -u temp_repo . - # If the diff command finds any differences, it will exit with a non-zero code and fail the workflow. - + diff -u -r ../temp_repo . + - name: Run static code analysis run: | cppcheck --enable=all --suppress=missingIncludeSystem --inconclusive --error-exitcode=1 . \ No newline at end of file From b827c5e82789530c88cfa62e39b992938c877785 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Mon, 25 Aug 2025 23:16:18 +0530 Subject: [PATCH 4/5] style: update formatting --- .github/workflows/ci.yml | 8 +++--- nn/include/linalg.h | 16 +++++------ nn/include/utils.h | 39 ++++++++++++++------------- nn/src/main.c | 6 ++--- nn/src/utils.c | 58 +++++++++++++++++++++------------------- 5 files changed, 66 insertions(+), 61 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96ba291..d3f13e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,13 +21,13 @@ jobs: mkdir -p ../temp_repo # Copy all files into the temporary directory cp -r . ../temp_repo - + # Now, format the copied source code find ../temp_repo -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google - + # Compare the original with the formatted code diff -u -r ../temp_repo . - + - name: Run static code analysis run: | - cppcheck --enable=all --suppress=missingIncludeSystem --inconclusive --error-exitcode=1 . \ No newline at end of file + cppcheck --enable=all --suppress=missingIncludeSystem --inconclusive --error-exitcode=1 . diff --git a/nn/include/linalg.h b/nn/include/linalg.h index bf6b9c4..1d1f6c6 100644 --- a/nn/include/linalg.h +++ b/nn/include/linalg.h @@ -2,7 +2,7 @@ // _matrix is used to avoid confusion if the struct is self referencing // 1D array used, this is way more performant than a 2D array is -typedef struct _Matrix{ +typedef struct _Matrix { double* matrix_data; int rows; int cols; @@ -30,18 +30,18 @@ void print_matrix(Matrix* m); void save_matrix(Matrix* m); int matrix_argmax(Matrix* m); - //============================ // Functions for Matrix Operations //============================ Matrix* identity_matrix(int n); -Matrix* add_matrix(Matrix *a, Matrix *b); +Matrix* add_matrix(Matrix* a, Matrix* b); Matrix* subtract_matrix(Matrix* a, Matrix* b); Matrix* multiply_matrix(Matrix* a, Matrix* b); -Matrix* apply_onto_matrix(double* (* func)(double), Matrix* m); // Apply our own stuff onto the matrix items, useful for activation -Matrix* add_scalar_to_matrix(Matrix *m, double n); +Matrix* apply_onto_matrix(double* (*func)(double), + Matrix* m); // Apply our own stuff onto the matrix + // items, useful for activation +Matrix* add_scalar_to_matrix(Matrix* m, double n); Matrix* dot_matrix(Matrix* a, Matrix* b); Matrix* transpose_matrix(Matrix* m); -Matrix* scale_matrix(double n, Matrix* m); // matrix can be scaled to non integer values - - +Matrix* scale_matrix(double n, + Matrix* m); // matrix can be scaled to non integer values diff --git a/nn/include/utils.h b/nn/include/utils.h index e4085ff..5252130 100644 --- a/nn/include/utils.h +++ b/nn/include/utils.h @@ -1,40 +1,41 @@ #pragma once +#include #include #include -#include #include // Set up log levels typedef enum { - LOG_LEVEL_DEBUG, - LOG_LEVEL_INFO, - LOG_LEVEL_WARN, - LOG_LEVEL_ERROR + LOG_LEVEL_DEBUG, + LOG_LEVEL_INFO, + LOG_LEVEL_WARN, + LOG_LEVEL_ERROR } LogLevel; // Set the minimum log level to display. Change this to filter output. #define MIN_LOG_LEVEL LOG_LEVEL_INFO // Assert macro, it'll be useful for checking matrix properties -#define ASSERT(condition, message) \ - do { \ - if (!(condition)) { \ - fprintf(stderr, "Assertion failed in %s at line %d: %s\n", \ - __FILE__, __LINE__, message); \ - exit(EXIT_FAILURE); \ - } \ - } while (0) +#define ASSERT(condition, message) \ + do { \ + if (!(condition)) { \ + fprintf(stderr, "Assertion failed in %s at line %d: %s\n", __FILE__, \ + __LINE__, message); \ + exit(EXIT_FAILURE); \ + } \ + } while (0) // For safe malloc allocations -#define CHECK_MALLOC(ptr, message) \ - ASSERT((ptr) != NULL, message);\ +#define CHECK_MALLOC(ptr, message) ASSERT((ptr) != NULL, message); // Function prototypes for logging void log_message(LogLevel level, const char* format, ...); // Convenience macros for easier logging -#define LOG_DEBUG(format, ...) log_message(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) -#define LOG_INFO(format, ...) log_message(LOG_LEVEL_INFO, format, ##__VA_ARGS__) -#define LOG_WARN(format, ...) log_message(LOG_LEVEL_WARN, format, ##__VA_ARGS__) -#define LOG_ERROR(format, ...) log_message(LOG_LEVEL_ERROR, format, ##__VA_ARGS__) \ No newline at end of file +#define LOG_DEBUG(format, ...) \ + log_message(LOG_LEVEL_DEBUG, format, ##__VA_ARGS__) +#define LOG_INFO(format, ...) log_message(LOG_LEVEL_INFO, format, ##__VA_ARGS__) +#define LOG_WARN(format, ...) log_message(LOG_LEVEL_WARN, format, ##__VA_ARGS__) +#define LOG_ERROR(format, ...) \ + log_message(LOG_LEVEL_ERROR, format, ##__VA_ARGS__) \ No newline at end of file diff --git a/nn/src/main.c b/nn/src/main.c index 22a297b..adc4e73 100644 --- a/nn/src/main.c +++ b/nn/src/main.c @@ -1,6 +1,6 @@ #include -int main(){ - printf("NN Program"); - return 0; +int main() { + printf("NN Program"); + return 0; } \ No newline at end of file diff --git a/nn/src/utils.c b/nn/src/utils.c index 80fc5a7..d4284cf 100644 --- a/nn/src/utils.c +++ b/nn/src/utils.c @@ -4,35 +4,39 @@ #include const char* get_log_level_string(LogLevel level) { - switch (level) { - case LOG_LEVEL_DEBUG: return "DEBUG"; - case LOG_LEVEL_INFO: return "INFO"; - case LOG_LEVEL_WARN: return "WARN"; - case LOG_LEVEL_ERROR: return "ERROR"; - default: return "UNKNOWN"; - } + switch (level) { + case LOG_LEVEL_DEBUG: + return "DEBUG"; + case LOG_LEVEL_INFO: + return "INFO"; + case LOG_LEVEL_WARN: + return "WARN"; + case LOG_LEVEL_ERROR: + return "ERROR"; + default: + return "UNKNOWN"; + } } void log_message(LogLevel level, const char* format, ...) { + if (level < MIN_LOG_LEVEL) { + return; + } - if (level < MIN_LOG_LEVEL) { - return; - } - - // include time - time_t now = time(NULL); - struct tm* t = localtime(&now); - char time_str[20]; - strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", t); - - FILE* stream = (level >= LOG_LEVEL_WARN) ? stderr : stdout; - - va_list args; - va_start(args, format); // sets pointer to the beginning of our args - - fprintf(stream, "[%s] [%s] ", time_str, get_log_level_string(level)); - vfprintf(stream, format, args); - fprintf(stream, "\n"); - - va_end(args); // cleans up va args memory + // include time + time_t now = time(NULL); + struct tm* t = localtime(&now); + char time_str[20]; + strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", t); + + FILE* stream = (level >= LOG_LEVEL_WARN) ? stderr : stdout; + + va_list args; + va_start(args, format); // sets pointer to the beginning of our args + + fprintf(stream, "[%s] [%s] ", time_str, get_log_level_string(level)); + vfprintf(stream, format, args); + fprintf(stream, "\n"); + + va_end(args); // cleans up va args memory } \ No newline at end of file From 34d62a93a3971566737b498fdd11861b8db1b246 Mon Sep 17 00:00:00 2001 From: Shreyash Date: Mon, 25 Aug 2025 23:20:29 +0530 Subject: [PATCH 5/5] fix: fix build errors, update actions --- .github/workflows/ci.yml | 9 ++------- nn/src/utils.c | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3f13e2..887c04e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,17 +17,12 @@ jobs: - name: Check code formatting run: | - # Create a temporary directory outside the current directory mkdir -p ../temp_repo - # Copy all files into the temporary directory cp -r . ../temp_repo - - # Now, format the copied source code find ../temp_repo -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google - - # Compare the original with the formatted code diff -u -r ../temp_repo . - name: Run static code analysis run: | - cppcheck --enable=all --suppress=missingIncludeSystem --inconclusive --error-exitcode=1 . + # The suppress flag tells cppcheck to ignore unused function warnings. + cppcheck --enable=all -I nn/include --suppress=missingIncludeSystem --suppress=unusedFunction --inconclusive --error-exitcode=1 . \ No newline at end of file diff --git a/nn/src/utils.c b/nn/src/utils.c index d4284cf..50271a7 100644 --- a/nn/src/utils.c +++ b/nn/src/utils.c @@ -25,7 +25,7 @@ void log_message(LogLevel level, const char* format, ...) { // include time time_t now = time(NULL); - struct tm* t = localtime(&now); + const struct tm* t = localtime(&now); char time_str[20]; strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", t);