From 7369b10a87aed982de328fbfa242666928e021d6 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 29 Apr 2012 23:21:35 +0200 Subject: Structs continued --- src/math/test/CMakeLists.txt | 14 +++ src/math/test/gendata.m | 86 +++++++++++++ src/math/test/matrix_test.cpp | 287 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 387 insertions(+) create mode 100644 src/math/test/CMakeLists.txt create mode 100644 src/math/test/gendata.m create mode 100644 src/math/test/matrix_test.cpp (limited to 'src/math/test') diff --git a/src/math/test/CMakeLists.txt b/src/math/test/CMakeLists.txt new file mode 100644 index 0000000..d82a9b9 --- /dev/null +++ b/src/math/test/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 2.8) + +set(CMAKE_BUILD_TYPE debug) +set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0") + +add_executable(matrix_test matrix_test.cpp) + +enable_testing() + +add_test(matrix_test ./matrix_test) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} DEPENDS matrix_test) + +add_custom_target(distclean COMMAND rm -rf ./matrix_test CMakeFiles Testing cmake_install.cmake CMakeCache.txt CTestTestfile.cmake Makefile) \ No newline at end of file diff --git a/src/math/test/gendata.m b/src/math/test/gendata.m new file mode 100644 index 0000000..5c13491 --- /dev/null +++ b/src/math/test/gendata.m @@ -0,0 +1,86 @@ +% Script in Octave for generating test data + +1; + +% Returns the minor matrix +function m = minor(A, r, c) + + m = A; + m(r,:) = []; + m(:,c) = []; + +end; + +% Returns the cofactor matrix +function m = cofactors(A) + + m = zeros(rows(A), columns(A)); + + for r = [1 : rows(A)] + for c = [1 : columns(A)] + m(r, c) = det(minor(A, r, c)); + if (mod(r + c, 2) == 1) + m(r, c) = -m(r, c); + end; + end; + end; + +end; + +% Prints the matrix as C++ code +function printout(A, name) + + printf('const float %s[16] = \n', name); + printf('{\n'); + + for c = [1 : columns(A)] + for r = [1 : rows(A)] + printf(' %f', A(r,c)); + if (! ( (r == 4) && (c == 4) ) ) + printf(','); + end; + printf('\n'); + end; + end; + + printf('};\n'); + +end; + +printf('// Cofactors\n'); +A = randn(4,4); +printout(A, 'COF_MAT'); +printf('\n'); +printout(cofactors(A), 'COF_RESULT'); +printf('\n'); + +printf('\n'); + +printf('// Det\n'); +A = randn(4,4); +printout(A, 'DET_MAT'); +printf('\n'); +printf('const float DET_RESULT = %f;', det(A)); +printf('\n'); + +printf('\n'); + +printf('// Invert\n'); +A = randn(4,4); +printout(A, 'INV_MAT'); +printf('\n'); +printout(inv(A), 'COF_RESULT'); +printf('\n'); + +printf('\n'); + +printf('// Multiplication\n'); +A = randn(4,4); +printout(A, 'MUL_A'); +printf('\n'); +B = randn(4,4); +printout(B, 'MUL_B'); +printf('\n'); +C = A * B; +printout(C, 'MUL_RESULT'); +printf('\n'); diff --git a/src/math/test/matrix_test.cpp b/src/math/test/matrix_test.cpp new file mode 100644 index 0000000..c7e9c01 --- /dev/null +++ b/src/math/test/matrix_test.cpp @@ -0,0 +1,287 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2012, Polish Portal of Colobot (PPC) +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// math/test/matrix_test.cpp + +/* Unit tests for Matrix struct + + Test data was randomly generated and the expected + results calculated using GNU Octave. + + */ + +#include "../func.h" +#include "../matrix.h" + +#include + +using namespace std; + +const float TEST_TOLERANCE = 1e-5; + +int TestCofactor() +{ + const float TEST_MATRIX[16] = + { + -0.306479, + -0.520207, + 0.127906, + 0.632922, + + -0.782876, + 0.015264, + 0.337479, + 1.466013, + + 0.072725, + -0.315123, + 1.613198, + -0.577377, + + 0.962397, + -1.320724, + 1.467588, + 0.579020 + }; + + const float EXPECTED_RESULTS[4][4] = + { + { 2.791599, -0.249952, 1.065075, -1.356570 }, + { 3.715943, -1.537511, 0.094812, -0.074520 }, + { 1.034500, -0.731752, -0.920756, -0.196235 }, + { 1.213928, -1.236857, 0.779741, -0.678482 } + }; + + Math::Matrix mat(TEST_MATRIX); + + for (int r = 0; r < 4; ++r) + { + for (int c = 0; c < 4; ++c) + { + float ret = mat.Cofactor(r, c); + float exp = EXPECTED_RESULTS[r][c]; + if (! Math::IsEqual(ret, exp, TEST_TOLERANCE)) + { + fprintf(stderr, "Cofactor r=%d, c=%d, %f (returned) != %f (expected)\n", r, c, ret, exp); + return 4*c+r; + } + } + } + + return 0; +} + +int TestDet() +{ + const float TEST_MATRIX[16] = + { + 0.85554, + 0.11624, + 1.30411, + 0.81467, + + 0.49692, + -1.92483, + -1.33543, + 0.85042, + + -0.16775, + 0.35344, + 1.40673, + 0.13961, + + 1.40709, + 0.11731, + 0.69042, + 0.91216 + }; + + const float EXPECTED_RESULT = 0.084360; + + float ret = Math::Matrix(TEST_MATRIX).Det(); + if (! Math::IsEqual(ret, EXPECTED_RESULT, TEST_TOLERANCE)) + { + fprintf(stderr, "Det %f (returned) != %f (expected)\n", ret, EXPECTED_RESULT); + return 1; + } + + return 0; +} + +int TestInvert() +{ + const float TEST_MATRIX[16] = + { + 1.4675123, + -0.2857923, + -0.0496217, + -1.2825408, + + -0.2804135, + -0.0826255, + -0.6825495, + 1.1661259, + + 0.0032798, + 0.5999200, + -1.8359883, + -1.1894424, + + -1.1501538, + -2.8792485, + 0.0299345, + 0.3730919 + }; + + const float EXPECTED_RESULT[16] = + { + 0.685863, + 0.562274, + -0.229722, + -0.132079, + + -0.266333, + -0.139862, + 0.054211, + -0.305568, + + -0.130817, + -0.494076, + -0.358226, + -0.047477, + + 0.069486, + 0.693649, + -0.261074, + -0.081200 + }; + + Math::Matrix mat(TEST_MATRIX); + mat.Invert(); + + if (! Math::MatricesEqual(mat, EXPECTED_RESULT, TEST_TOLERANCE)) + { + fprintf(stderr, "Invert mismatch\n"); + return 1; + } + + return 0; +} + +int TestMultiply() +{ + const float TEST_MATRIX_A[16] = + { + -1.931420, + 0.843410, + 0.476929, + -0.493435, + 1.425659, + -0.176331, + 0.129096, + 0.551081, + -0.543530, + -0.190783, + -0.084744, + 1.379547, + -0.473377, + 1.643398, + 0.400539, + 0.702937 + }; + + const float TEST_MATRIX_B[16] = + { + 0.3517561, + 1.3903778, + -0.8048254, + -0.4090024, + + -1.5542159, + -0.6798636, + 1.6003393, + -0.1467117, + + 0.5043620, + -0.0068779, + 2.0697285, + -0.0463650, + + 0.9605451, + -0.4620149, + 1.2525952, + -1.3409909 + }; + + const float EXPECTED_RESULT[16] = + { + 1.933875, + -0.467099, + 0.251638, + -0.805156, + + 1.232207, + -1.737383, + -1.023401, + 2.496859, + + -2.086953, + -0.044468, + 0.045688, + 2.570036, + + -2.559921, + -1.551155, + -0.244802, + 0.056808 + }; + + Math::Matrix matA(TEST_MATRIX_A); + Math::Matrix matB(TEST_MATRIX_B); + + Math::Matrix mat; + Math::MultiplyMatrices(matA, matB, mat); + if (! Math::MatricesEqual(mat, Math::Matrix(EXPECTED_RESULT), TEST_TOLERANCE ) ) + { + fprintf(stderr, "Multiply mismath!\n"); + return 1; + } + + return 0; +} + +int main() +{ + int result = 0; + + result = TestCofactor(); + if (result != 0) + return result; + + result = TestDet(); + if (result != 0) + return result; + + result = TestInvert(); + if (result != 0) + return result; + + result = TestMultiply(); + if (result != 0) + return result; + + return result; +} -- cgit v1.2.3-1-g7c22