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..887c04e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,28 @@ +# .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: | + mkdir -p ../temp_repo + cp -r . ../temp_repo + find ../temp_repo -name "*.c" -o -name "*.h" | xargs clang-format -i --style=Google + diff -u -r ../temp_repo . + + - name: Run static code analysis + run: | + # 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/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..50271a7 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); + const 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