From 411f66a2540fa17c736116d865e0ceb0cfe5623b Mon Sep 17 00:00:00 2001 From: jeanne Date: Wed, 11 May 2022 09:54:38 -0700 Subject: Initial commit. --- src/lib/test/matrix_test.c | 350 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 src/lib/test/matrix_test.c (limited to 'src/lib/test/matrix_test.c') diff --git a/src/lib/test/matrix_test.c b/src/lib/test/matrix_test.c new file mode 100644 index 0000000..8191c97 --- /dev/null +++ b/src/lib/test/matrix_test.c @@ -0,0 +1,350 @@ +#include + +#include "test.h" +#include "test_util.h" + +#include +#include + +// static void PrintMatrix(const nnMatrix* matrix) { +// assert(matrix); + +// for (int i = 0; i < matrix->rows; ++i) { +// for (int j = 0; j < matrix->cols; ++j) { +// printf("%f ", nnMatrixAt(matrix, i, j)); +// } +// printf("\n"); +// } +// } + +TEST_CASE(nnMatrixMake_1x1) { + nnMatrix A = nnMatrixMake(1, 1); + TEST_EQUAL(A.rows, 1); + TEST_EQUAL(A.cols, 1); +} + +TEST_CASE(nnMatrixMake_3x1) { + nnMatrix A = nnMatrixMake(3, 1); + TEST_EQUAL(A.rows, 3); + TEST_EQUAL(A.cols, 1); +} + +TEST_CASE(nnMatrixInit_3x1) { + nnMatrix A = nnMatrixMake(3, 1); + nnMatrixInit(&A, (R[]) { 1, 2, 3 }); + TEST_EQUAL(A.values[0], 1); + TEST_EQUAL(A.values[1], 2); + TEST_EQUAL(A.values[2], 3); +} + +TEST_CASE(nnMatrixCopyCol_test) { + nnMatrix A = nnMatrixMake(3, 2); + nnMatrix B = nnMatrixMake(3, 1); + + nnMatrixInit(&A, (R[]) { + 1, 2, + 3, 4, + 5, 6, + }); + + nnMatrixCopyCol(&A, &B, 1, 0); + + TEST_EQUAL(nnMatrixAt(&B, 0, 0), 2); + TEST_EQUAL(nnMatrixAt(&B, 1, 0), 4); + TEST_EQUAL(nnMatrixAt(&B, 2, 0), 6); + + nnMatrixDel(&A); + nnMatrixDel(&B); +} + +TEST_CASE(nnMatrixMul_square_3x3) { + nnMatrix A = nnMatrixMake(3, 3); + nnMatrix B = nnMatrixMake(3, 3); + nnMatrix O = nnMatrixMake(3, 3); + + nnMatrixInit(&A, (const R[]){ + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + }); + nnMatrixInit(&B, (const R[]){ + 2, 4, 3, + 6, 8, 5, + 1, 7, 9, + }); + nnMatrixMul(&A, &B, &O); + + const R expected[3][3] = { + { 17, 41, 40 }, + { 44, 98, 91 }, + { 71, 155, 142 }, + }; + for (int i = 0; i < O.rows; ++i) { + for (int j = 0; j < O.cols; ++j) { + TEST_TRUE(double_eq(nnMatrixAt(&O, i, j), expected[i][j], EPS)); + } + } + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&O); +} + +TEST_CASE(nnMatrixMul_non_square_2x3_3x1) { + nnMatrix A = nnMatrixMake(2, 3); + nnMatrix B = nnMatrixMake(3, 1); + nnMatrix O = nnMatrixMake(2, 1); + + nnMatrixInit(&A, (const R[]){ + 1, 2, 3, + 4, 5, 6, + }); + nnMatrixInit(&B, (const R[]){ + 2, + 6, + 1, + }); + nnMatrixMul(&A, &B, &O); + + const R expected[2][1] = { + { 17 }, + { 44 }, + }; + for (int i = 0; i < O.rows; ++i) { + for (int j = 0; j < O.cols; ++j) { + TEST_TRUE(double_eq(nnMatrixAt(&O, i, j), expected[i][j], EPS)); + } + } + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&O); +} + +TEST_CASE(nnMatrixMulAdd_test) { + nnMatrix A = nnMatrixMake(2, 3); + nnMatrix B = nnMatrixMake(2, 3); + nnMatrix O = nnMatrixMake(2, 3); + const R scale = 2; + + nnMatrixInit(&A, (const R[]){ + 1, 2, 3, + 4, 5, 6, + }); + nnMatrixInit(&B, (const R[]){ + 2, 3, 1, + 7, 4, 3 + }); + nnMatrixMulAdd(&A, &B, scale, &O); // O = A + B * scale + + const R expected[2][3] = { + { 5, 8, 5 }, + { 18, 13, 12 }, + }; + for (int i = 0; i < O.rows; ++i) { + for (int j = 0; j < O.cols; ++j) { + TEST_TRUE(double_eq(nnMatrixAt(&O, i, j), expected[i][j], EPS)); + } + } + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&O); +} + +TEST_CASE(nnMatrixMulSub_test) { + nnMatrix A = nnMatrixMake(2, 3); + nnMatrix B = nnMatrixMake(2, 3); + nnMatrix O = nnMatrixMake(2, 3); + const R scale = 2; + + nnMatrixInit(&A, (const R[]){ + 1, 2, 3, + 4, 5, 6, + }); + nnMatrixInit(&B, (const R[]){ + 2, 3, 1, + 7, 4, 3 + }); + nnMatrixMulSub(&A, &B, scale, &O); // O = A - B * scale + + const R expected[2][3] = { + { -3, -4, 1 }, + { -10, -3, 0 }, + }; + for (int i = 0; i < O.rows; ++i) { + for (int j = 0; j < O.cols; ++j) { + TEST_TRUE(double_eq(nnMatrixAt(&O, i, j), expected[i][j], EPS)); + } + } + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&O); +} + +TEST_CASE(nnMatrixMulPairs_2x3) { + nnMatrix A = nnMatrixMake(2, 3); + nnMatrix B = nnMatrixMake(2, 3); + nnMatrix O = nnMatrixMake(2, 3); + + nnMatrixInit(&A, (const R[]){ + 1, 2, 3, + 4, 5, 6, + }); + nnMatrixInit(&B, (const R[]){ + 2, 3, 1, + 7, 4, 3 + }); + nnMatrixMulPairs(&A, &B, &O); + + const R expected[2][3] = { + { 2, 6, 3 }, + { 28, 20, 18 }, + }; + for (int i = 0; i < O.rows; ++i) { + for (int j = 0; j < O.cols; ++j) { + TEST_TRUE(double_eq(nnMatrixAt(&O, i, j), expected[i][j], EPS)); + } + } + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&O); +} + +TEST_CASE(nnMatrixAdd_square_2x2) { + nnMatrix A = nnMatrixMake(2, 2); + nnMatrix B = nnMatrixMake(2, 2); + nnMatrix C = nnMatrixMake(2, 2); + + nnMatrixInit(&A, (R[]) { + 1, 2, + 3, 4, + }); + nnMatrixInit(&B, (R[]) { + 2, 1, + 5, 3, + }); + + nnMatrixAdd(&A, &B, &C); + + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 0), 3, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 1), 3, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 0), 8, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 1), 7, EPS)); + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&C); +} + +TEST_CASE(nnMatrixSub_square_2x2) { + nnMatrix A = nnMatrixMake(2, 2); + nnMatrix B = nnMatrixMake(2, 2); + nnMatrix C = nnMatrixMake(2, 2); + + nnMatrixInit(&A, (R[]) { + 1, 2, + 3, 4, + }); + nnMatrixInit(&B, (R[]) { + 2, 1, + 5, 3, + }); + + nnMatrixSub(&A, &B, &C); + + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 0), -1, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 1), +1, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 0), -2, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 1), +1, EPS)); + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&C); +} + +TEST_CASE(nnMatrixAddRow_test) { + nnMatrix A = nnMatrixMake(2, 3); + nnMatrix B = nnMatrixMake(1, 3); + nnMatrix C = nnMatrixMake(2, 3); + + nnMatrixInit(&A, (R[]) { + 1, 2, 3, + 4, 5, 6, + }); + nnMatrixInit(&B, (R[]) { + 2, 1, 3, + }); + + nnMatrixAddRow(&A, &B, &C); + + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 0), 3, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 1), 3, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 0, 2), 6, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 0), 6, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 1), 6, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&C, 1, 2), 9, EPS)); + + nnMatrixDel(&A); + nnMatrixDel(&B); + nnMatrixDel(&C); +} + +TEST_CASE(nnMatrixTranspose_square_2x2) { + nnMatrix A = nnMatrixMake(2, 2); + nnMatrix B = nnMatrixMake(2, 2); + + nnMatrixInit(&A, (R[]) { + 1, 2, + 3, 4 + }); + + nnMatrixTranspose(&A, &B); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 0), 1, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 1), 3, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 1, 0), 2, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 1, 1), 4, EPS)); + + nnMatrixDel(&A); + nnMatrixDel(&B); +} + +TEST_CASE(nnMatrixTranspose_non_square_2x1) { + nnMatrix A = nnMatrixMake(2, 1); + nnMatrix B = nnMatrixMake(1, 2); + + nnMatrixInit(&A, (R[]) { + 1, + 3, + }); + + nnMatrixTranspose(&A, &B); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 0), 1, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 1), 3, EPS)); + + nnMatrixDel(&A); + nnMatrixDel(&B); +} + +TEST_CASE(nnMatrixGt_test) { + nnMatrix A = nnMatrixMake(2, 3); + nnMatrix B = nnMatrixMake(2, 3); + + nnMatrixInit(&A, (R[]) { + -3, 2, 0, + 4, -1, 5 + }); + + nnMatrixGt(&A, 0, &B); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 0), 0, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 1), 1, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 0, 2), 0, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 1, 0), 1, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 1, 1), 0, EPS)); + TEST_TRUE(double_eq(nnMatrixAt(&B, 1, 2), 1, EPS)); + + nnMatrixDel(&A); + nnMatrixDel(&B); +} -- cgit v1.2.3