From 3feecc2b0ee9b1607ffae1f6fd86b7c942db1de1 Mon Sep 17 00:00:00 2001 From: "dario.genga" <dario.genga@etu.hesge.ch> Date: Mon, 22 Nov 2021 18:22:55 +0100 Subject: [PATCH] Add matrix allocation, initialisation and print Also added the tests for the allocation and initiaisation. --- main.c | 9 ++++++--- makefile | 12 +++++++++--- matrix.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- matrix.h | 36 ++++++++++++++++++++++++++++++++++-- test.c | 25 +++++++++++++++++++++++++ tests | Bin 0 -> 32016 bytes 6 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 test.c create mode 100755 tests diff --git a/main.c b/main.c index b524a78..0a04670 100644 --- a/main.c +++ b/main.c @@ -1,16 +1,19 @@ /* Author : Dario GENGA - * Date : 13.10.2021 - * Description : Template for a standard c file + * Date : 16.11.2021 + * Description : Manipulate matrix */ #include <stdio.h> #include <stdlib.h> // #include <math.h> // #include <time.h> +// #include <stdbool.h> #include "matrix.h" int main() { - printf("Hello world!"); + matrix mat; + matrix_init(&mat, 3, 4, 0); + matrix_print(mat); return EXIT_SUCCESS; } diff --git a/makefile b/makefile index 30b4034..07e07fb 100644 --- a/makefile +++ b/makefile @@ -1,12 +1,18 @@ LIB=-lm CC=gcc -Wall -Wextra -g -matrix:matrix.o main.o - gcc $^ -fsanitize=address -o $@ $(LIB) +run_tests: tests + ./$< + +matrix: matrix.o main.o + $(CC) $^ -fsanitize=address -fsanitize=leak -o $@ $(LIB) + +tests: test.o matrix.o + $(CC) $^ -fsanitize=address -fsanitize=leak -o $@ $(LIB) matrix.o: matrix.c matrix.h $(CC) -c $< $(LIB) main.o: main.c $(CC) -c $< $(LIB) clean: - rm -f *.o matrix \ No newline at end of file + rm -f *.o matrix tests \ No newline at end of file diff --git a/matrix.c b/matrix.c index 920e761..64fe388 100644 --- a/matrix.c +++ b/matrix.c @@ -1,11 +1,58 @@ /* Author : Dario GENGA - * Date : 15.11.2021 - * Description : Manipulate an unidimensional array with dynamic memory allocation + * Date : 16.11.2021 + * Description : Manipulate matrix */ #include "matrix.h" #include <stdio.h> +error_code matrix_alloc(matrix *mat, int32_t m, int32_t n) { + int32_t **data = malloc(m * sizeof(int32_t *)); + mat->m = m; + mat->n = n; + + if (data == NULL) { + return err; + } + mat->data = data; + + for (int32_t i = 0; i < m; i++) { + int32_t *row = malloc(n * sizeof(int32_t *)); + + if (row == NULL) { + return err; + } + + mat->data[i] = row; + } + + return ok; +} + +error_code matrix_init(matrix *mat, int32_t m, int32_t n, int32_t val) { + matrix_alloc(mat, m, n); + + for (int32_t i = 0; i < m; i++) { + for (int32_t k = 0; k < n; k++) { + mat->data[i][k] = val; + } + } + + return ok; +} + +error_code matrix_print(const matrix mat) { + for (int i = 0; i < mat.m; i++) { + printf("["); + for (int k = 0; k < mat.n; k++) { + printf(" %d ", mat.data[i][k]); + } + printf("]\n"); + } + + return ok; +} + void swap(int *x, int *y) { int tmp = *x; diff --git a/matrix.h b/matrix.h index ee830b6..a614f66 100644 --- a/matrix.h +++ b/matrix.h @@ -1,11 +1,43 @@ /* Author : Dario GENGA - * Date : 15.11.2021 - * Description : Manipulate an unidimensional array with dynamic memory allocation + * Date : 16.11.2021 + * Description : Manipulate matrix */ #ifndef _MATRIX_H #define _MATRIX_H #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> + +typedef struct _matrix { + int32_t m, n; + int32_t ** data; +} matrix; + +typedef enum _error_code { + ok, err +} error_code; + +error_code matrix_alloc(matrix *mat, int32_t m, int32_t n); + +error_code matrix_init(matrix *mat, int32_t m, int32_t n, int32_t val); + +error_code matrix_destroy(matrix *mat); + +error_code matrix_init_from_array(matrix *mat, int32_t m, int32_t n, int32_t data[], int32_t s); + +error_code matrix_clone(matrix *cloned, const matrix mat); + +error_code matrix_transpose(matrix *transposed, const matrix mat); + +error_code matrix_print(const matrix mat); + +error_code matrix_extract_submatrix(matrix *sub, const matrix mat, int32_t m0, int32_t m1, int32_t n0, int32_t n1); + +bool matrix_is_equal(matrix mat1, matrix mat2); + +error_code matrix_get(int32_t *elem, const matrix mat, int32_t ix, int32_t iy); + +error_code matrix_set(matrix mat, int32_t ix, int32_t iy, int32_t elem); void swap(int *x, int *y); diff --git a/test.c b/test.c new file mode 100644 index 0000000..e34b3b4 --- /dev/null +++ b/test.c @@ -0,0 +1,25 @@ +/* Author : Dario GENGA + * Date : 16.11.2021 + * Description : Manipulate matrix + */ +#include "matrix.h" +#include <assert.h> +#include <math.h> +#include <stdbool.h> +#include <stdio.h> + +int main() { + // Initialisation + matrix mat; + int32_t m = 3; + int32_t n = 4; + int32_t val = 1; + printf("Starting the tests...\n"); + // Test allocation + assert(matrix_alloc(&mat, m, n) == ok); + // Test initialisation + assert(matrix_init(&mat, m, n, val) == ok); + + printf("The tests are completed and were successful !"); + return EXIT_SUCCESS; +} diff --git a/tests b/tests new file mode 100755 index 0000000000000000000000000000000000000000..9fcfc55a0f9140259233a074e457e80538bc020f GIT binary patch literal 32016 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 literal 0 HcmV?d00001 -- GitLab