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