diff --git a/main.c b/main.c index b524a783ddc17aa49ec0e739f79203f29ba9f024..bf04085420f06083131721016f75981992ed1eb6 100644 --- a/main.c +++ b/main.c @@ -1,16 +1,63 @@ /* 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 "matrix.h" int main() { - printf("Hello world!"); + matrix mat, cloned, transposed, sub; + int32_t m = 3; + int32_t n = 4; + int32_t s = m * n; + int32_t val = 0; + int32_t data[12] = { 2, 1, -1, -2, 3, 1, 1, 3, 1, 4, -1, -1 }; + // Init + matrix_init(&mat, m, n, val); + printf("Empty matrix %dx%d\n", m, n); + matrix_print(mat); + // Init from array + matrix_init_from_array(&mat, m, n, data, s); + printf("Matrix %dx%d from array\n", m, n); + matrix_print(mat); + // Clone + matrix_clone(&cloned, mat); + printf("Cloned matrix :\n"); + matrix_print(cloned); + // Transpose + matrix_transpose(&transposed, mat); + printf("Transposed matrix :\n"); + matrix_print(transposed); + // Sub matrix + matrix_extract_submatrix(&sub, transposed, 1, 4, 1, 3); + printf("Sub matrix :\n"); + matrix_print(sub); + // Equal + if (matrix_is_equal(mat, cloned)) { + printf("The following matrix are equals :\n"); + } else { + printf("The following matrix are not equals :\n"); + } + printf("Matrix 1\n"); + matrix_print(mat); + printf("Matrix 2\n"); + matrix_print(cloned); + // Get & set + int32_t element; + matrix_get(&element, mat, 0, 0); + printf("First element of the first matrix : %d\n", element); + matrix_set(mat, 0, 0, 42); + printf("The first element of the first matrix has been changed :\n"); + matrix_print(mat); + + // Free the memory + matrix_destroy(&mat); + matrix_destroy(&cloned); + matrix_destroy(&transposed); + matrix_destroy(&sub); + return EXIT_SUCCESS; } diff --git a/makefile b/makefile index 30b4034d349004523261f19b8a2d521fa7fcfb4d..07e07fb52c8a2d771c7e8bf0c2f7cf18096a49ca 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 920e761dd3b05dbc9b7c6dd534b23b2fa24656d8..5d5c313a312166f5d1976bcb962470ae6a19ea1e 100644 --- a/matrix.c +++ b/matrix.c @@ -1,14 +1,178 @@ /* 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> -void swap(int *x, int *y) -{ - int tmp = *x; - *x = *y; - *y = tmp; +error_code matrix_alloc(matrix *mat, int32_t m, int32_t n) { + if (m <= 0 || n <= 0) { + return err; + } + + 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) { + if (m <= 0 || n <= 0) { + return err; + } + + 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_init_from_array(matrix *mat, int32_t m, int32_t n, int32_t data[], int32_t s) { + if (m <= 0 || n <= 0 || m * n != s) { + return err; + } + + matrix_alloc(mat, m, n); + + for (int i = 0; i < m; i++) { + for (int k = 0; k < n; k++) { + mat->data[i][k] = data[k + (i * n)]; + } + } + + 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; +} + +error_code matrix_clone(matrix *cloned, const matrix mat) { + error_code code = matrix_alloc(cloned, mat.m, mat.n); + if (code == err) { + return err; + } + + for (int i = 0; i < mat.m; i++) { + for (int k = 0; k < mat.n; k++) { + cloned->data[i][k] = mat.data[i][k]; + } + } + + return ok; +} + +error_code matrix_destroy(matrix *mat) { + // Free each row + for (int32_t i = 0; i < mat->m; i++) { + free(mat->data[i]); + } + + // Free the data and reset the number of row and col + free(mat->data); + mat->m = -1; + mat->n = -1; + mat->data = NULL; + + return ok; +} + +error_code matrix_transpose(matrix *transposed, const matrix mat) { + error_code code = matrix_alloc(transposed, mat.n, mat.m); + if (code == err) { + return err; + } + + for (int i = 0; i < mat.m; i++) { + for (int k = 0; k < mat.n; k++) { + transposed->data[k][i] = mat.data[i][k]; + } + } + + return ok; +} + +error_code matrix_extract_submatrix(matrix *sub, const matrix mat, int32_t m0, int32_t m1, int32_t n0, int32_t n1) { + if (m0 < 0 || m1 > mat.m || n0 < 0 || n1 > mat.n || m0 > m1 || n0 > n1) { + return err; + } + + error_code code = matrix_alloc(sub, m1 - m0 , n1 - n0 ); + if (code == err) { + return err; + } + + for (int i = m0; i < m1; i++) { + for (int k = n0; k < n1; k++) { + sub->data[i - m0][k - n0] = mat.data[i][k]; + } + } + + return ok; +} + + +bool matrix_is_equal(matrix mat1, matrix mat2) { + if (mat1.m != mat2.m || mat1.n != mat2.n) { + return false; + } + + // Parse each values of the matrix + for (int i = 0; i < mat1.m; i++) { + for (int k = 0; k < mat1.n; k++) { + if (mat1.data[i][k] != mat2.data[i][k]) { + return false; + } + } + } + return true; +} + +error_code matrix_get(int32_t *elem, const matrix mat, int32_t ix, int32_t iy) { + if (ix < 0 || iy < 0 || iy >= mat.m || ix >= mat.n) { + return err; + } + *elem = mat.data[iy][ix]; + + return ok; +} + + +error_code matrix_set(matrix mat, int32_t ix, int32_t iy, int32_t elem) { + if (ix < 0 || iy < 0 || ix > mat.m || iy > mat.n) { + return err; + } + mat.data[iy][ix] = elem; + + return ok; } diff --git a/matrix.h b/matrix.h index ee830b65601b0ba90f6b078f844b11bb494d8f0c..c4729ea3ef8af525c7cc3ca80394f0c7f914cf42 100644 --- a/matrix.h +++ b/matrix.h @@ -1,12 +1,42 @@ /* 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> -void swap(int *x, int *y); +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); #endif \ No newline at end of file diff --git a/test.c b/test.c new file mode 100644 index 0000000000000000000000000000000000000000..9e9918430249b88413d188dbd0a1534a8fee4a7c --- /dev/null +++ b/test.c @@ -0,0 +1,49 @@ +/* Author : Dario GENGA + * Date : 16.11.2021 + * Description : Manipulate matrix + */ +#include "matrix.h" +#include <assert.h> +#include <stdbool.h> +#include <stdio.h> + +int main() { + // Initialisation + matrix mat; + matrix cloned; + matrix transposed; + matrix sub; + int32_t m = 3; + int32_t n = 4; + int32_t val = 1; + int32_t first_elem = 2; + int32_t set_elem = 100; + int32_t data[12] = { first_elem, 1, -1, -2, 3, 1, 1, 3, 1, 4, -1, -1 }; + int32_t elem; + // Starting the tests... + printf("Starting the tests...\n"); + assert(matrix_alloc(&mat, m, n) == ok); + assert(matrix_destroy(&mat) == ok); + assert(matrix_init(&mat, m, n, val) == ok); + assert(matrix_destroy(&mat) == ok); + assert(matrix_init(&mat, -1, n, val) == err); + assert(matrix_destroy(&mat) == ok); + assert(matrix_init_from_array(&mat, m, n, data, m*n) == ok); + assert(matrix_clone(&cloned, mat) == ok); + assert(matrix_transpose(&transposed, mat) == ok); + assert(matrix_print(mat) == ok); + assert(matrix_extract_submatrix(&sub, mat, 0, 2, 0, 2) == ok); + assert(matrix_is_equal(mat, cloned) == true); + assert(matrix_get(&elem, mat, 0, 0) == ok); + assert(mat.data[0][0] == first_elem); + assert(matrix_set(mat, 0, 0, set_elem) == ok); + assert(mat.data[0][0] == set_elem); + assert(matrix_destroy(&mat) == ok); + matrix_destroy(&cloned); + matrix_destroy(&transposed); + matrix_destroy(&sub); + + + printf("The tests are completed and were successful !\n"); + return EXIT_SUCCESS; +} diff --git a/tests b/tests new file mode 100755 index 0000000000000000000000000000000000000000..cdf7679023159a823f7a880a0cb3df0001d843d5 Binary files /dev/null and b/tests differ