From e406487051ee276df24e0aae15cee277fdcde4e6 Mon Sep 17 00:00:00 2001
From: Weiqi Feng <weltch1997@gmail.com>
Date: Fri, 24 Feb 2023 19:01:53 -0500
Subject: [PATCH] Add files via upload

---
 CMakeLists.txt       |  20 +++++++
 apps/CMakeLists.txt  |   2 +
 apps/app.c           |  63 ++++++++++++++++++++++
 include/field.h      |  22 ++++++++
 include/group.h      |  19 +++++++
 include/matrix.h     |  25 +++++++++
 include/vector.h     |  22 ++++++++
 src/CMakeLists.txt   |  16 ++++++
 src/field.c          |  29 ++++++++++
 src/group.c          |  25 +++++++++
 src/matrix.c         | 122 +++++++++++++++++++++++++++++++++++++++++++
 src/vector.c         |  32 ++++++++++++
 tests/CMakeLists.txt |  17 ++++++
 tests/test_field.c   |  62 ++++++++++++++++++++++
 tests/test_group.c   |  45 ++++++++++++++++
 tests/test_matrix.c  |  82 +++++++++++++++++++++++++++++
 tests/test_vector.c  |  63 ++++++++++++++++++++++
 17 files changed, 666 insertions(+)
 create mode 100644 CMakeLists.txt
 create mode 100644 apps/CMakeLists.txt
 create mode 100644 apps/app.c
 create mode 100644 include/field.h
 create mode 100644 include/group.h
 create mode 100644 include/matrix.h
 create mode 100644 include/vector.h
 create mode 100644 src/CMakeLists.txt
 create mode 100644 src/field.c
 create mode 100644 src/group.c
 create mode 100644 src/matrix.c
 create mode 100644 src/vector.c
 create mode 100644 tests/CMakeLists.txt
 create mode 100644 tests/test_field.c
 create mode 100644 tests/test_group.c
 create mode 100644 tests/test_matrix.c
 create mode 100644 tests/test_vector.c

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..2e5b590
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.24)
+project(
+        PPANN
+        VERSION 0.1
+        DESCRIPTION "Test"
+        LANGUAGES C
+)
+
+if (CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
+    set(CMAKE_C_STANDARD 17)
+    set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+    include(CTest)
+endif()
+
+
+find_library(RELIC_LIB relic)
+
+add_subdirectory(src)
+add_subdirectory(apps)
+add_subdirectory(tests)
\ No newline at end of file
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
new file mode 100644
index 0000000..2333fb5
--- /dev/null
+++ b/apps/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_executable(app app.c)
+target_link_libraries(app PRIVATE ppann_lib)
\ No newline at end of file
diff --git a/apps/app.c b/apps/app.c
new file mode 100644
index 0000000..9508f4e
--- /dev/null
+++ b/apps/app.c
@@ -0,0 +1,63 @@
+#include "field.h"
+#include "group.h"
+#include <stdio.h>
+#include "relic/relic.h"
+
+
+int main() {
+    core_init();
+    pc_param_set_any();
+
+//
+//    g a, b;
+//    gt x, y;
+//
+//    // Get generator and map to target group, x =
+//    generator(a);
+//    map(a, a, x);
+//
+//
+//    g1_print(a);
+//    printf("\n");
+//    gt_print(x);
+//    printf("\n");
+//
+//    // Multiply and Exp.
+//    zp m, n;
+//    zp_from_int(m, 5);
+//    zp_from_int(n, 5);
+//
+//    // b = a^5, y = gt^10
+//    multiply(b, a, m);
+//
+//    g1_print(b);
+//    printf("\n");
+//
+//    exponentiation(y, x, n);
+//
+//    gt_free(x);
+//    map(b, b, x);
+//
+//    printf("Compare: %i", gt_cmp(y, x));
+
+    g1_t a, b;
+    gt_t x, y, z;
+
+    g1_get_gen(a);
+
+    g1_print(a);
+
+    g1_mul_dig(b, a, 5);
+
+    g1_print(b);
+
+    pc_map(x, a, a);
+
+    pc_map(y, b, b);
+
+    gt_exp_dig(z, x, 25);
+
+    printf("Compare: %i", gt_cmp(y, z) == RLC_EQ);
+
+    return 0;
+}
\ No newline at end of file
diff --git a/include/field.h b/include/field.h
new file mode 100644
index 0000000..6c09690
--- /dev/null
+++ b/include/field.h
@@ -0,0 +1,22 @@
+#ifndef PPANN_FIELD_H
+#define PPANN_FIELD_H
+
+#include "relic/relic.h"
+
+typedef fp_t zp;
+
+void rand_zp(zp x);
+
+void zp_zero(zp x);
+
+void zp_copy(zp x_copy, zp x);
+
+void zp_from_int(zp x, int x_int);
+
+void zp_add(zp r, zp x, zp y);
+
+void zp_multiply(zp p, zp x, zp y);
+
+void zp_inverse(zp xi, zp x);
+
+#endif //PPANN_FIELD_H
\ No newline at end of file
diff --git a/include/group.h b/include/group.h
new file mode 100644
index 0000000..85c8954
--- /dev/null
+++ b/include/group.h
@@ -0,0 +1,19 @@
+#ifndef PPANN_GROUP_H
+#define PPANN_GROUP_H
+
+#include "field.h"
+
+typedef g1_t g;
+typedef gt_t gt;
+
+void generator(g x);
+
+void negate(g nx, g x);
+
+void multiply(g r, g x, zp y);
+
+void exponentiation(gt r, gt x, zp y);
+
+void map(g a, g b, gt r);
+
+#endif //PPANN_GROUP_H
diff --git a/include/matrix.h b/include/matrix.h
new file mode 100644
index 0000000..e13a4d2
--- /dev/null
+++ b/include/matrix.h
@@ -0,0 +1,25 @@
+#ifndef PPANN_MATRIX_H
+#define PPANN_MATRIX_H
+
+#include "field.h"
+#include "group.h"
+
+typedef zp* zp_mat;
+
+void matrix_zp_from_int(zp_mat x, int *int_mat, int row, int col);
+
+void matrix_zp_rand(zp_mat x, int row, int col);
+
+void matrix_identity(zp_mat x, int size);
+
+int matrix_is_identity(zp_mat x, int size);
+
+void matrix_transpose(zp_mat xt, zp_mat x, int row, int col);
+
+void matrix_merge(zp_mat xy, zp_mat x, zp_mat y, int row, int col_x, int col_y);
+
+void matrix_multiply(zp_mat xy, zp_mat x, zp_mat y, int row_x, int row_y, int col_y);
+
+void matrix_inverse(zp_mat xi, zp_mat x, int size);
+
+#endif //PPANN_MATRIX_H
diff --git a/include/vector.h b/include/vector.h
new file mode 100644
index 0000000..27c1c5c
--- /dev/null
+++ b/include/vector.h
@@ -0,0 +1,22 @@
+#ifndef PPANN_VECTOR_H
+#define PPANN_VECTOR_H
+
+#include "field.h"
+#include "group.h"
+
+typedef zp *zp_vec;
+typedef g *g_vec;
+
+void vector_zp_from_int(zp_vec x, int *int_vec, int length);
+
+void vector_zp_rand(zp_vec x, int length);
+
+void vector_merge(zp_vec r, zp_vec a, zp_vec b, int size_a, int size_b);
+
+void vector_add(zp_vec r, zp_vec a, zp_vec b, int size);
+
+void vector_raise(g base, zp_vec x, g_vec gx, int size);
+
+void inner_product(gt r, g_vec a, g_vec b, int size);
+
+#endif //PPANN_VECTOR_H
\ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 0000000..1b1c1ad
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(HEADER_LIST "${CMAKE_SOURCE_DIR}/include/")
+
+add_library(ppann_lib field.c group.c vector.c matrix.c ${HEADER_LIST})
+
+# We need this directory, and users of our library will need it too
+target_include_directories(ppann_lib PUBLIC ../include)
+
+# This depends on (header only) boost
+target_link_libraries(ppann_lib PRIVATE ${RELIC_LIB})
+
+# IDEs should put the headers in a nice place
+source_group(
+        TREE "${PROJECT_SOURCE_DIR}/include"
+        PREFIX "Header Files"
+        FILES ${HEADER_LIST}
+)
diff --git a/src/field.c b/src/field.c
new file mode 100644
index 0000000..82b6d37
--- /dev/null
+++ b/src/field.c
@@ -0,0 +1,29 @@
+#include "field.h"
+
+void rand_zp(dig_t *x) {
+    fp_rand(x);
+}
+
+void zp_zero(dig_t *x) {
+    fp_zero(x);
+}
+
+void zp_copy(dig_t *x_copy, dig_t *x) {
+    fp_copy(x_copy, x);
+}
+
+void zp_from_int(dig_t *x, int y) {
+    fp_set_dig(x, y);
+}
+
+void zp_add(dig_t *r, dig_t *x, dig_t *y) {
+    fp_add(r, x, y);
+}
+
+void zp_multiply(dig_t *p, dig_t *x, dig_t *y) {
+    fp_mul(p, x, y);
+}
+
+void zp_inverse(dig_t *xi, dig_t *x) {
+    fp_inv(xi, x);
+}
\ No newline at end of file
diff --git a/src/group.c b/src/group.c
new file mode 100644
index 0000000..1868a3b
--- /dev/null
+++ b/src/group.c
@@ -0,0 +1,25 @@
+#include "group.h"
+
+void generator(ep_st *x) {
+    g1_get_gen(x);
+}
+
+void negate(ep_st *nx, ep_st *x) {
+    g1_neg(nx, x);
+}
+
+void multiply(ep_st *r, ep_st *x, dig_t *y) {
+    bn_t new_y;
+    fp_prime_back(new_y, y);
+    g1_mul(r, x, new_y);
+}
+
+void exponentiation(fp_t *r, fp_t *x, dig_t *y) {
+    bn_t new_y;
+    fp_prime_back(new_y, y);
+    gt_exp(r, x, new_y);
+}
+
+void map(ep_st *a, ep_st *b, fp_t *r) {
+    pc_map(r, a, b);
+}
diff --git a/src/matrix.c b/src/matrix.c
new file mode 100644
index 0000000..ecc3e54
--- /dev/null
+++ b/src/matrix.c
@@ -0,0 +1,122 @@
+#include "matrix.h"
+
+void matrix_zp_from_int(zp_mat x, int *int_mat, int row, int 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]);
+        }
+    }
+}
+
+void matrix_zp_rand(zp_mat x, int row, int col) {
+    for (int i = 0; i < row; i++) {
+        for (int j = 0; j < col; j++) {
+            rand_zp(x[i * col + j]);
+        }
+    }
+}
+
+void matrix_identity(zp_mat x, int 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]);
+        }
+    }
+}
+
+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;
+}
+
+void matrix_transpose(zp_mat xt, zp_mat x, int row, int 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]);
+        }
+    }
+}
+
+void matrix_merge(zp_mat xy, zp_mat x, zp_mat y, int row, int col_x, int 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]);
+        }
+    }
+}
+
+void matrix_multiply(zp_mat xy, zp_mat x, zp_mat y, int row_x, int row_y, int col_y) {
+    zp temp;
+    for (int i = 0; i < row_x; i++) {
+        for (int j = 0; j < col_y; j++) {
+            zp_from_int(xy[i * row_y + j], 0);
+            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);
+            }
+        }
+    }
+}
+
+void matrix_inverse(zp_mat xi, zp_mat x, int size) {
+    // Declare the row echelon matrix and generate it.
+    zp *identity, *row_echelon;
+    identity = (zp *) malloc(size * size * sizeof(zp));
+    row_echelon = (zp *) malloc(2 * size * size * sizeof(zp));
+    matrix_identity(identity, size);
+    matrix_merge(row_echelon, 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 && fp_cmp_dig(row_echelon[i * 2 * size + j], 1) != RLC_EQ) {
+                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 && fp_cmp_dig(row_echelon[i * 2 * size + j], 0) == RLC_EQ) 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]);
+                    fp_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]);
+                fp_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.
+    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]);
+        }
+    }
+}
diff --git a/src/vector.c b/src/vector.c
new file mode 100644
index 0000000..43ac6d0
--- /dev/null
+++ b/src/vector.c
@@ -0,0 +1,32 @@
+#include "vector.h"
+
+void vector_zp_from_int(zp_vec x, int *int_vec, int length) {
+    for (int i = 0; i < length; i++) zp_from_int(x[i], int_vec[i]);
+}
+
+void vector_zp_rand(zp_vec x, int length) {
+    for (int i = 0; i < length; i++) rand_zp(x[i]);
+}
+
+void vector_merge(zp_vec r, zp_vec a, zp_vec b, int size_a, int size_b) {
+    for (int i = 0; i < size_a; i++) zp_copy(r[i], a[i]);
+    for (int i = 0; i < size_b; i++) zp_copy(r[i + size_a], b[i]);
+}
+
+void vector_add(zp_vec r, zp_vec a, zp_vec b, int size) {
+    for (int i = 0; i < size; i++) zp_add(r[i], a[i], b[i]);
+}
+
+void vector_raise(ep_st base[1], zp_vec x, g_vec gx, int size) {
+    for (int i = 0; i < size; i++) multiply(gx[i], base, x[i]);
+}
+
+void inner_product(gt r, g_vec a, g_vec b, int size) {
+    pc_map_sim(r, a, b, size);
+}
+
+
+
+
+
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..ef1621d
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,17 @@
+# Add tests as separate executables.
+add_executable(test_field test_field.c)
+add_executable(test_group test_group.c)
+add_executable(test_vector test_vector.c)
+add_executable(test_matrix test_matrix.c)
+
+# Link tests to the main library.
+target_link_libraries(test_field PRIVATE ppann_lib)
+target_link_libraries(test_group PRIVATE ppann_lib)
+target_link_libraries(test_vector PRIVATE ppann_lib)
+target_link_libraries(test_matrix PRIVATE ppann_lib)
+
+# Register the previous tests.
+add_test(NAME test_field COMMAND test_field)
+add_test(NAME test_group COMMAND test_group)
+add_test(NAME test_vector COMMAND test_vector)
+add_test(NAME test_matrix COMMAND test_matrix)
\ No newline at end of file
diff --git a/tests/test_field.c b/tests/test_field.c
new file mode 100644
index 0000000..d51f818
--- /dev/null
+++ b/tests/test_field.c
@@ -0,0 +1,62 @@
+#include "field.h"
+
+int test_zp_zero() {
+    zp x, y;
+    zp_zero(x);
+    fp_zero(y);
+    return fp_cmp(x, y);
+}
+
+int test_zp_copy() {
+    zp x, y;
+    zp_from_int(x, 3);
+    zp_copy(y, x);
+    return fp_cmp_dig(y, 3);
+}
+
+int test_zp_from_int() {
+    zp x;
+    zp_from_int(x, 3);
+    return fp_cmp_dig(x, 3);
+}
+
+int test_zp_add() {
+    zp x, y, r;
+    zp_from_int(x, 10);
+    zp_from_int(y, 20);
+    zp_add(r, x, y);
+    return fp_cmp_dig(r, 30);
+}
+
+int test_zp_multiply() {
+    zp x, y, r;
+    zp_from_int(x, 10);
+    zp_from_int(y, 20);
+    zp_multiply(r, x, y);
+    return fp_cmp_dig(r, 200);
+}
+
+int test_zp_inverse() {
+    zp x, xi, r;
+    rand_zp(x);
+    zp_inverse(xi, x);
+    zp_multiply(r, x, xi);
+    return fp_cmp_dig(r, 1);
+}
+
+
+int main() {
+    // Init core and setup.
+    core_init();
+    pc_param_set_any();
+
+    // Perform tests.
+    if (test_zp_zero() != RLC_EQ) return 1;
+    if (test_zp_copy() != RLC_EQ) return 1;
+    if (test_zp_from_int() != RLC_EQ) return 1;
+    if (test_zp_add() != RLC_EQ) return 1;
+    if (test_zp_multiply() != RLC_EQ) return 1;
+    if (test_zp_inverse() != RLC_EQ) return 1;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/tests/test_group.c b/tests/test_group.c
new file mode 100644
index 0000000..0e6b9d1
--- /dev/null
+++ b/tests/test_group.c
@@ -0,0 +1,45 @@
+#include "group.h"
+
+int test_generator() {
+    g x;
+    generator(x);
+    return g1_is_valid(x);
+}
+
+int test_all() {
+    // Set integers.
+    zp m, n;
+    zp_from_int(m, 5);
+    zp_from_int(n, 25);
+
+    // Declare variables.
+    g a, b;
+    gt x, y, z;
+
+    // Get generator g and find g^5.
+    generator(a);
+    multiply(b, a, m);
+
+    // Get e(g, g) and e(g^5, g^5).
+    map(a, a, x);
+    map(b, b, y);
+
+    // Get e(g, g)^25.
+    exponentiation(z, x, n);
+
+    // Compare e(g^5, g^5) with e(g, g)^25.
+    return gt_cmp(y, z);
+}
+
+int main(){
+    // Init core and setup.
+    core_init();
+    fp_prime_init();
+    pc_param_set_any();
+
+    // Perform tests.
+    if (test_generator() != 1) return 1;
+    if (test_all() != RLC_EQ) return 1;
+
+    return 0;
+}
\ No newline at end of file
diff --git a/tests/test_matrix.c b/tests/test_matrix.c
new file mode 100644
index 0000000..2f17074
--- /dev/null
+++ b/tests/test_matrix.c
@@ -0,0 +1,82 @@
+#include "matrix.h"
+
+int test_zp_from_int() {
+    int row = 3, col = 3;
+    zp x[row * col];
+    int int_vec[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+    matrix_zp_from_int(x, int_vec, 3, 3);
+    return fp_cmp_dig(x[2 * col + 2], 9);
+}
+
+int test_transpose() {
+    int row = 3, col = 3;
+    zp x[row * col], xt[col * row];
+    matrix_zp_rand(x, row, col);
+    matrix_transpose(xt, x, row, col);
+    return fp_cmp(xt[col - 1], x[2 * row]);
+}
+
+int test_identity() {
+    int size = 1000;
+    zp *x;
+    x = (zp *) malloc(size * size * sizeof(zp));
+    matrix_identity(x, size);
+    return matrix_is_identity(x, size);
+}
+
+int test_merge() {
+    int size = 10;
+    zp xy[(size + size) * size], x[size * size], y[size * size];
+    matrix_zp_rand(x, size, size);
+    matrix_identity(y, size);
+    matrix_merge(xy, x, y, size, size, size);
+    return fp_cmp(x[2 * size + 1], xy[4 * size + 1]);
+}
+
+int test_multiply_vector() {
+    int int_x[5] = {1, 2, 3, 4, 5};
+    int int_y[15] = {10, 20, 30,
+                     10, 20, 30,
+                     10, 20, 30,
+                     10, 20, 30,
+                     10, 20, 30};
+
+    zp x[5], y[15];
+    matrix_zp_from_int(x, int_x, 1, 5);
+    matrix_zp_from_int(y, int_y, 5, 3);
+
+    zp xy[3];
+    matrix_multiply(xy, x, y, 1, 5, 3);
+
+    return fp_cmp_dig(xy[1], 300);
+}
+
+int test_inverse() {
+    int size = 100;
+    // Allocate space.
+    zp *x, *xi, *r;
+    x = (zp *) malloc(size * size * sizeof(zp));
+    xi = (zp *) malloc(size * size * sizeof(zp));
+    r = (zp *) malloc(size * size * sizeof(zp));
+    matrix_zp_rand(x, size, size);
+    matrix_inverse(xi, x, size);
+    matrix_multiply(r, xi, x, size, size, size);
+    return matrix_is_identity(r, size);
+}
+
+
+int main() {
+    // Init core and setup.
+    core_init();
+    pc_param_set_any();
+
+    // Perform tests.
+    if (test_zp_from_int() != RLC_EQ) 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
diff --git a/tests/test_vector.c b/tests/test_vector.c
new file mode 100644
index 0000000..91e27a7
--- /dev/null
+++ b/tests/test_vector.c
@@ -0,0 +1,63 @@
+#include "vector.h"
+
+int test_zp_from_int() {
+    zp x[4];
+    int int_vec[4] = {1, 2, 3, 4};
+    vector_zp_from_int(x, int_vec, 4);
+    return fp_cmp_dig(x[3], 4);
+}
+
+int test_merge_vector() {
+    zp x[3], y[3], z[6];
+    int int_vec_x[3] = {1, 2, 3};
+    int int_vec_y[3] = {11, 22, 33};
+    vector_zp_from_int(x, int_vec_x, 3);
+    vector_zp_from_int(y, int_vec_y, 3);
+    vector_merge(z, x, y, 3, 3);
+    return fp_cmp_dig(z[5], 33);
+}
+
+int test_add_vector() {
+    zp x[3], y[3], z[3];
+    int int_vec_x[3] = {1, 2, 3};
+    int int_vec_y[3] = {11, 22, 33};
+    vector_zp_from_int(x, int_vec_x, 3);
+    vector_zp_from_int(y, int_vec_y, 3);
+    vector_add(z, x, y, 3);
+    return fp_cmp_dig(z[2], 36);
+}
+
+int test_inner_product() {
+    zp x[3], y[3];
+    int int_vec_x[3] = {1, 2, 3};
+    int int_vec_y[3] = {4, 5, 6};
+    vector_zp_from_int(x, int_vec_x, 3);
+    vector_zp_from_int(y, int_vec_y, 3);
+
+    g g, gx[3], gy[3];
+    generator(g);
+    vector_raise(g, x, gx, 3);
+    vector_raise(g, y, gy, 3);
+
+    gt b, r;
+    inner_product(r, gx, gy, 3);
+    map(g, g, b);
+    gt_exp_dig(b, b, 32);
+
+    return gt_cmp(b, r);
+}
+
+
+int main() {
+    // Init core and setup.
+    core_init();
+    pc_param_set_any();
+
+    // Perform tests.
+    if (test_zp_from_int() != RLC_EQ) return 1;
+    if (test_merge_vector() != RLC_EQ) return 1;
+    if (test_add_vector() != RLC_EQ) return 1;
+    if (test_inner_product() != RLC_EQ) return 1;
+
+    return 0;
+}
\ No newline at end of file
-- 
GitLab