diff --git a/include/matrix.h b/include/matrix.h
index 8a6a2ecfbe775ae1aeac61d05befa48385dff4d1..b3c8e7a8c081aa0b4cd2dc307dd5231b4ea6d347 100644
--- a/include/matrix.h
+++ b/include/matrix.h
@@ -1,25 +1,25 @@
-//#ifndef PPANN_MATRIX_H
-//#define PPANN_MATRIX_H
-//
-//#include "field.h"
-//#include "group.h"
-//
-//typedef zp* zp_mat;
-//
-//zp_mat matrix_zp_from_int(int *int_mat, int row, int col);
-//
-//zp_mat matrix_zp_rand(int row, int col);
-//
-//zp_mat matrix_identity(int size);
-//
-//int matrix_is_identity(zp_mat x, int size);
-//
-//zp_mat matrix_transpose(zp_mat x, int row, int col);
-//
-//zp_mat matrix_merge(zp_mat x, zp_mat y, int row, int col_x, int col_y);
-//
-//zp_mat matrix_multiply(zp_mat x, zp_mat y, int row_x, int row_y, int col_y);
-//
-//zp_mat matrix_inverse(zp_mat x, int size);
-//
-//#endif //PPANN_MATRIX_H
+#ifndef PPANN_MATRIX_H
+#define PPANN_MATRIX_H
+
+#include "field.h"
+#include "group.h"
+
+typedef struct zp *zp_mat;
+
+zp_mat matrix_zp_from_int(const int *int_mat, int row, int col, bn_t modular);
+
+zp_mat matrix_zp_rand(int row, int col, bn_t modular);
+
+zp_mat matrix_identity(int size, bn_t modular);
+
+int matrix_is_identity(zp_mat x, int size);
+
+zp_mat matrix_transpose(zp_mat x, int row, int col);
+
+zp_mat matrix_merge(zp_mat x, zp_mat y, int row, int col_x, int col_y);
+
+zp_mat matrix_multiply(zp_mat x, zp_mat y, int row_x, int row_y, int col_y, bn_t modular);
+
+zp_mat matrix_inverse(zp_mat x, int size, bn_t modular);
+
+#endif //PPANN_MATRIX_H
\ No newline at end of file
diff --git a/src/matrix.c b/src/matrix.c
index 78001e6513db5b14a1f7ea3431c509a55ecedeb0..f83056481cf4130de0812bbf9f985e2b74e37f1c 100644
--- a/src/matrix.c
+++ b/src/matrix.c
@@ -1,143 +1,138 @@
-//#include "matrix.h"
-//
-//zp_mat matrix_zp_from_int(int *int_mat, int row, int col) {
-// zp_mat x;
-// x = (zp_mat) malloc(sizeof(zp) * row * col);
-// for (int i = 0; i < row; i++) {
-// for (int j = 0; j < col; j++) {
-// zp_from_int(x[i * col + j], int_mat[i * col + j]);
-// }
-// }
-// return x;
-//}
-//
-//zp_mat matrix_zp_rand(int row, int col) {
-// zp_mat x;
-// x = (zp_mat) malloc(sizeof(zp) * row * col);
-// for (int i = 0; i < row; i++) {
-// for (int j = 0; j < col; j++) {
-// rand_zp(x[i * col + j]);
-// }
-// }
-// return x;
-//}
-//
-//zp_mat matrix_identity(int size) {
-// zp_mat x;
-// x = (zp_mat) malloc(sizeof(zp) * size * size);
-// for (int i = 0; i < size; i++) {
-// for (int j = 0; j < size; j++) {
-// if (i == j) zp_from_int(x[i * size + j], 1);
-// else zp_zero(x[i * size + j]);
-// }
-// }
-// return x;
-//}
-//
-//int matrix_is_identity(zp_mat x, int size) {
-// for (int i = 0; i < size; i++) {
-// for (int j = 0; j < size; j++) {
-// if (i == j && fp_cmp_dig(x[i * size + j], 1) != RLC_EQ) return 0;
-// if (i != j && fp_cmp_dig(x[i * size + j], 0) != RLC_EQ) return 0;
-// }
-// }
-// return 1;
-//}
-//
-//zp_mat matrix_transpose(zp_mat x, int row, int col) {
-// zp_mat xt;
-// xt = (zp_mat) malloc(sizeof(zp) * row * col);
-// for (int i = 0; i < row; i++) {
-// for (int j = 0; j < col; j++) {
-// zp_copy(xt[j * row + i], x[i * col + j]);
-// }
-// }
-// return xt;
-//}
-//
-//zp_mat matrix_merge(zp_mat x, zp_mat y, int row, int col_x, int col_y) {
-// zp_mat xy;
-// xy = (zp_mat) malloc(sizeof(zp) * row * (col_x + col_y));
-// for (int i = 0; i < row; i++) {
-// for (int j = 0; j < col_x; j++) {
-// zp_copy(xy[i * (col_x + col_y) + j], x[i * col_x + j]);
-// }
-// for (int j = 0; j < col_y; j++) {
-// zp_copy(xy[i * (col_x + col_y) + col_x + j], y[i * col_y + j]);
-// }
-// }
-// return xy;
-//}
-//
-//zp_mat matrix_multiply(zp_mat x, zp_mat y, int row_x, int row_y, int col_y) {
-// zp temp;
-// zp_mat xy;
-// xy = (zp_mat) malloc(sizeof(zp) * row_x * col_y);
-//
-// for (int i = 0; i < row_x; i++) {
-// for (int j = 0; j < col_y; j++) {
-// zp_zero(xy[i * row_y + j]);
-// for (int k = 0; k < row_y; k++) {
-// zp_multiply(temp, x[i * row_y + k], y[k * col_y + j]);
-// zp_add(xy[i * col_y + j], xy[i * col_y + j], temp);
-// }
-// }
-// }
-// return xy;
-//}
-//
-//zp_mat matrix_inverse(zp_mat x, int size) {
-// // Declare the row echelon matrix and generate it.
-// zp_mat identity, row_echelon;
-// identity = matrix_identity(size);
-// row_echelon = matrix_merge(x, identity, size, size, size);
-//
-// // Declare temp value.
-// zp temp_multiplier, temp_neg;
-//
-// // Bottom left half to all zeros.
-// for (int i = 0; i < size; i++) {
-// for (int j = i; j < size; j++) {
-// if (i == j && !zp_is_int(row_echelon[i * 2 * size + j], 1)) {
-// zp_inverse(temp_multiplier, row_echelon[i * 2 * size + i]);
-// for (int k = i; k < size * 2; k++) {
-// zp_multiply(row_echelon[j * 2 * size + k], row_echelon[j * 2 * size + k], temp_multiplier);
-// }
-// }
-//
-// if (i == j && zp_is_int(row_echelon[i * 2 * size + j], 0)) break;
-//
-// if (i != j) {
-// zp_copy(temp_multiplier, row_echelon[j * 2 * size + i]);
-// for (int k = i; k < size * 2; k++) {
-// zp_multiply(temp_neg, temp_multiplier, row_echelon[i * 2 * size + k]);
-// zp_neg(temp_neg, temp_neg);
-// zp_add(row_echelon[j * 2 * size + k], row_echelon[j * 2 * size + k], temp_neg);
-// }
-// }
-// }
-// }
-//
-// // Top right half to all zeros.
-// for (int i = size - 1; i > 0; i--) {
-// for (int j = i - 1; j >= 0; j--) {
-// zp_copy(temp_multiplier, row_echelon[j * 2 * size + i]);
-// for (int k = i; k < size * 2; k++) {
-// zp_multiply(temp_neg, temp_multiplier, row_echelon[i * 2 * size + k]);
-// zp_neg(temp_neg, temp_neg);
-// zp_add(row_echelon[j * 2 * size + k], row_echelon[j * 2 * size + k], temp_neg);
-// }
-// }
-// }
-//
-//
-// // Copy over the output.
-// zp_mat xi;
-// xi = (zp_mat) malloc(sizeof(zp) * size * size);
-// for (int i = 0; i < size; i++) {
-// for (int j = 0; j < size; j++) {
-// zp_copy(xi[i * size + j], row_echelon[i * 2 * size + size + j]);
-// }
-// }
-// return xi;
-//}
\ No newline at end of file
+#include "matrix.h"
+
+zp_mat matrix_zp_from_int(const int *int_mat, int row, int col, bn_st *modular) {
+ zp_mat x;
+ x = (zp_mat) malloc(sizeof(struct zp) * row * col);
+ for (int i = 0; i < row; i++) {
+ for (int j = 0; j < col; j++) {
+ x[i * col + j] = zp_from_int(int_mat[i * col + j], modular);
+ }
+ }
+ return x;
+}
+
+zp_mat matrix_zp_rand(int row, int col, bn_st *modular) {
+ zp_mat x;
+ x = (zp_mat) malloc(sizeof(struct zp) * row * col);
+ for (int i = 0; i < row; i++) {
+ for (int j = 0; j < col; j++) {
+ x[i * col + j] = rand_zp(modular);
+ }
+ }
+ return x;
+}
+
+zp_mat matrix_identity(int size, bn_st *modular) {
+ zp_mat x;
+ x = (zp_mat) malloc(sizeof(struct zp) * size * size);
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ if (i == j) x[i * size + j] = zp_one(modular);
+ else x[i * size + j] = zp_zero(modular);
+ }
+ }
+ return x;
+}
+
+int matrix_is_identity(zp_mat x, int size) {
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ if (i == j && !zp_cmp_int(x[i * size + j], 1)) return 0;
+ if (i != j && !zp_cmp_int(x[i * size + j], 0)) return 0;
+ }
+ }
+ return 1;
+}
+
+zp_mat matrix_transpose(zp_mat x, int row, int col) {
+ zp_mat xt;
+ xt = (zp_mat) malloc(sizeof(struct zp) * row * col);
+ for (int i = 0; i < row; i++) {
+ for (int j = 0; j < col; j++) {
+ xt[j * row + i] = zp_copy(x[i * col + j]);
+ }
+ }
+ return xt;
+}
+
+zp_mat matrix_merge(zp_mat x, zp_mat y, int row, int col_x, int col_y) {
+ zp_mat xy;
+ xy = (zp_mat) malloc(sizeof(struct zp) * row * (col_x + col_y));
+ for (int i = 0; i < row; i++) {
+ for (int j = 0; j < col_x; j++) {
+ xy[i * (col_x + col_y) + j] = zp_copy(x[i * col_x + j]);
+ }
+ for (int j = 0; j < col_y; j++) {
+ xy[i * (col_x + col_y) + col_x + j] = zp_copy(y[i * col_y + j]);
+ }
+ }
+ return xy;
+}
+
+zp_mat matrix_multiply(zp_mat x, zp_mat y, int row_x, int row_y, int col_y, bn_st *modular) {
+ zp_mat xy = (zp_mat) malloc(sizeof(struct zp) * row_x * col_y);
+
+ for (int i = 0; i < row_x; i++) {
+ for (int j = 0; j < col_y; j++) {
+ xy[i * row_y + j] = zp_zero(modular);
+ for (int k = 0; k < row_y; k++) {
+ xy[i * col_y + j] = zp_add(xy[i * col_y + j], zp_mul(x[i * row_y + k], y[k * col_y + j]));
+ }
+ }
+ }
+ return xy;
+}
+
+zp_mat matrix_inverse(zp_mat x, int size, bn_st *modular) {
+ // Declare the row echelon matrix and generate it.
+ zp_mat identity = matrix_identity(size, modular);
+ zp_mat row_echelon = matrix_merge(x, identity, size, size, size);
+
+ // Declare temp value.
+ struct zp temp_multiplier, temp_neg;
+
+ // Bottom left half to all zeros.
+ for (int i = 0; i < size; i++) {
+ for (int j = i; j < size; j++) {
+ if (i == j && !zp_cmp_int(row_echelon[i * 2 * size + j], 1)) {
+ temp_multiplier = zp_inv(row_echelon[i * 2 * size + i]);
+ for (int k = i; k < size * 2; k++) {
+ row_echelon[j * 2 * size + k] = zp_mul(row_echelon[j * 2 * size + k], temp_multiplier);
+ }
+ }
+
+ if (i == j && zp_cmp_int(row_echelon[i * 2 * size + j], 0)) break;
+
+ if (i != j) {
+ temp_multiplier = zp_copy(row_echelon[j * 2 * size + i]);
+ for (int k = i; k < size * 2; k++) {
+ temp_neg = zp_mul(temp_multiplier, row_echelon[i * 2 * size + k]);
+ temp_neg = zp_neg(temp_neg);
+ row_echelon[j * 2 * size + k] = zp_add(row_echelon[j * 2 * size + k], temp_neg);
+ }
+ }
+ }
+ }
+
+ // Top right half to all zeros.
+ for (int i = size - 1; i > 0; i--) {
+ for (int j = i - 1; j >= 0; j--) {
+ temp_multiplier = zp_copy(row_echelon[j * 2 * size + i]);
+ for (int k = i; k < size * 2; k++) {
+ temp_neg = zp_mul(temp_multiplier, row_echelon[i * 2 * size + k]);
+ temp_neg = zp_neg(temp_neg);
+ row_echelon[j * 2 * size + k] = zp_add(row_echelon[j * 2 * size + k], temp_neg);
+ }
+ }
+ }
+
+ // Copy over the output.
+ zp_mat xi;
+ xi = (zp_mat) malloc(sizeof(struct zp) * size * size);
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < size; j++) {
+ xi[i * size + j] = zp_copy(row_echelon[i * 2 * size + size + j]);
+ }
+ }
+ return xi;
+}
\ No newline at end of file
diff --git a/tests/test_matrix.c b/tests/test_matrix.c
index 60c81f3450a8bc588f18f97c7ce38ac71cffdbe0..6610e354dc03e0c85db08e500aabff45babe13ec 100644
--- a/tests/test_matrix.c
+++ b/tests/test_matrix.c
@@ -1,78 +1,69 @@
-//#include "matrix.h"
-//
-//int test_zp_from_int() {
-// zp_mat x;
-// int int_mat[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
-// x = matrix_zp_from_int(int_mat, 3, 3);
-// return zp_is_int(x[8], 9);
-//}
-//
-//int test_transpose() {
-// int row = 3, col = 3;
-// zp_mat x, xt;
-// x = matrix_zp_rand(row, col);
-// xt = matrix_transpose(x, row, col);
-// return fp_cmp(xt[col - 1], x[2 * row]);
-//}
-//
-//int test_identity() {
-// int size = 100;
-// zp_mat x;
-// x = matrix_identity(size);
-// return matrix_is_identity(x, size);
-//}
-//
-//int test_merge() {
-// int size = 10;
-// zp_mat xy, x, y;
-// x = matrix_zp_rand(size, size);
-// y = matrix_identity(size);
-// xy = matrix_merge(x, y, size, size, size);
-// return fp_cmp(x[2 * size + 1], xy[4 * size + 1]);
-//}
-//
-//int test_multiply_vector() {
-// int mat_x[5] = {1, 2, 3, 4, 5};
-// int mat_y[15] = {10, 20, 30,
-// 10, 20, 30,
-// 10, 20, 30,
-// 10, 20, 30,
-// 10, 20, 30};
-//
-// zp_mat x, y, xy;
-// x = matrix_zp_from_int(mat_x, 1, 5);
-// y = matrix_zp_from_int(mat_y, 5, 3);
-// xy = matrix_multiply(x, y, 1, 5, 3);
-//
-// return fp_cmp_dig(xy[1], 300);
-//}
-//
-//int test_inverse() {
-// int size = 100;
-// // Allocate space.
-// zp_mat x, xi, r;
-// x = matrix_zp_rand(size, size);
-// xi = matrix_inverse(x, size);
-// r = matrix_multiply(xi, x, size, size, size);
-// return matrix_is_identity(r, size);
-//}
-//
-//int main() {
-// // Init core and setup.
-// core_init();
-// pc_param_set_any();
+#include "matrix.h"
-//// Get order.
-//bn_t N;
-//pc_get_ord(N);
-//
-// // Perform tests.
-// if (test_zp_from_int() != 1) return 1;
-// if (test_transpose() != RLC_EQ) return 1;
-// if (test_identity() != 1) return 1;
-// if (test_merge() != RLC_EQ) return 1;
-// if (test_multiply_vector() != RLC_EQ) return 1;
-// if (test_inverse() != 1) return 1;
-//
-// return 0;
-//}
\ No newline at end of file
+int test_zp_from_int(bn_st *N) {
+ int int_mat[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ zp_mat x = matrix_zp_from_int(int_mat, 3, 3, N);
+ return zp_cmp_int(x[8], 9);
+}
+
+int test_transpose(bn_st *N) {
+ int row = 3, col = 3;
+ zp_mat x = matrix_zp_rand(row, col, N);
+ zp_mat xt = matrix_transpose(x, row, col);
+ return zp_cmp(xt[col - 1], x[2 * row]);
+}
+
+int test_identity(bn_st *N) {
+ int size = 10;
+ zp_mat x = matrix_identity(size, N);
+ return matrix_is_identity(x, size);
+}
+
+int test_merge(bn_st *N) {
+ int size = 10;
+ zp_mat x = matrix_zp_rand(size, size, N);
+ zp_mat y = matrix_identity(size, N);
+ zp_mat xy = matrix_merge(x, y, size, size, size);
+ return zp_cmp(x[2 * size + 1], xy[4 * size + 1]);
+}
+
+int test_multiply_vector(bn_st *N) {
+ int mat_x[5] = {1, 2, 3, 4, 5};
+ int mat_y[15] = {10, 20, 30,
+ 10, 20, 30,
+ 10, 20, 30,
+ 10, 20, 30,
+ 10, 20, 30};
+ zp_mat x = matrix_zp_from_int(mat_x, 1, 5, N);
+ zp_mat y = matrix_zp_from_int(mat_y, 5, 3, N);
+ zp_mat xy = matrix_multiply(x, y, 1, 5, 3, N);
+ return zp_cmp_int(xy[2], 450);
+}
+
+int test_inverse(bn_st *N) {
+ int size = 100;
+ zp_mat x = matrix_zp_rand(size, size, N);
+ zp_mat xi = matrix_inverse(x, size, N);
+ zp_mat r = matrix_multiply(x, xi, size, size, size, N);
+ return matrix_is_identity(r, size);
+}
+
+int main() {
+ // Init core and setup.
+ core_init();
+ pc_param_set_any();
+
+ // Get order.
+ bn_t N;
+ pc_get_ord(N);
+
+ // Perform tests.
+ if (test_zp_from_int(N) != 1) return 1;
+ if (test_transpose(N) != 1) return 1;
+ if (test_identity(N) != 1) return 1;
+ if (test_merge(N) != 1) return 1;
+ if (test_multiply_vector(N) != 1) return 1;
+ if (test_inverse(N) != 1) return 1;
+
+ return 0;
+}
\ No newline at end of file