//================================================================================================== /* ROTGEN - Runtime Overlay for Eigen Copyright : CODE RECKONS SPDX-License-Identifier: BSL-1.0 */ //================================================================================================== #include "unit/tests.hpp" #include template void for_each_element(EigenType const& m, F&& f) { for(rotgen::Index i = 0; i < m.rows(); ++i) for(rotgen::Index j = 0; j < m.cols(); ++j) f(i, j, m(i,j)); } template void for_each_element(EigenType& m, F&& f) { for(rotgen::Index i = 0; i < m.rows(); ++i) for(rotgen::Index j = 0; j < m.cols(); ++j) f(i, j, m(i,j)); } template MatrixType make_initialized_matrix(rotgen::tests::matrix_block_test_case const& matrix_construct) { MatrixType matrix(matrix_construct.rows, matrix_construct.cols); for(rotgen::Index i = 0; i < matrix_construct.rows; ++i) for(rotgen::Index j = 0; j < matrix_construct.cols; ++j) matrix(i, j) = static_cast(matrix_construct.init_fn(i, j)); return matrix; } template void validate_block_behavior(MatrixType& matrix, BlockType& block, rotgen::Index i0, rotgen::Index j0, rotgen::Index ni, rotgen::Index nj) { TTS_EQUAL(block.rows(), ni); TTS_EQUAL(block.cols(), nj); TTS_EQUAL(block.size(), ni * nj); // test block values for_each_element(block, [&](auto i, auto j, auto val) { TTS_EQUAL(val, matrix(i0 + i, j0 + j)); }); // test aliasing T value = 1; for_each_element(block, [&](auto i, auto j, auto&) { block(i, j) = value++; }); value = 1; for_each_element(block, [&](auto i, auto j, auto&) { TTS_EQUAL(matrix(i0 + i, j0 + j), value++); }); for_each_element(block, [&](auto i, auto j, auto&) { matrix(i0 + i, j0 + j) = T(42); }); for_each_element(block, [&](auto&, auto&, auto val) { TTS_EQUAL(val, T(42)); }); } template void test_dynamic_block_extraction(rotgen::tests::matrix_block_test_case const& matrix_construct) { MatrixType matrix = make_initialized_matrix(matrix_construct); auto block_main = rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj); auto block_top_left_corner = rotgen::topLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj); auto block_top_right_corner = rotgen::topRightCorner(matrix, matrix_construct.ni, matrix_construct.nj); auto block_bottom_left_corner = rotgen::bottomLeftCorner(matrix, matrix_construct.ni, matrix_construct.nj); auto block_bottom_right_corner = rotgen::bottomRightCorner(matrix, matrix_construct.ni, matrix_construct.nj); auto block_top_rows = rotgen::topRows(matrix, matrix_construct.ni); auto block_middle_rows = rotgen::middleRows(matrix, matrix_construct.i0, matrix_construct.ni); auto block_bottom_rows = rotgen::bottomRows(matrix, matrix_construct.ni); auto block_left_cols = rotgen::leftCols(matrix, matrix_construct.nj); auto block_middle_cols = rotgen::middleCols(matrix, matrix_construct.j0, matrix_construct.nj); auto block_right_cols = rotgen::rightCols(matrix, matrix_construct.nj); auto blocks = std::make_tuple( std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj), std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni, matrix_construct.nj), std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj), std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix_construct.nj), std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj), std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols()), std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, matrix.cols()), std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix.cols()), std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj), std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(), matrix_construct.nj), std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, matrix.rows(), matrix_construct.nj) ); std::apply([&](auto&&... block_entries) { (([&] { auto&& [block, i_offset, j_offset, ni, nj] = block_entries; using block_t = std::remove_reference_t; TTS_EQUAL(block_t::RowsAtCompileTime, rotgen::Dynamic); TTS_EQUAL(block_t::ColsAtCompileTime, rotgen::Dynamic); TTS_EQUAL(block_t::storage_order, MatrixType::storage_order); validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); })(), ...); }, blocks); } template void test_static_block_extraction(rotgen::tests::static_matrix_block_test_case const& matrix_construct) { MatrixType matrix(matrix_construct.rows, matrix_construct.cols); for (rotgen::Index i = 0; i < matrix_construct.rows; ++i) for (rotgen::Index j = 0; j < matrix_construct.cols; ++j) matrix(i, j) = static_cast(matrix_construct.init_fn(i, j)); auto block_main = rotgen::extract(matrix, matrix_construct.i0, matrix_construct.j0); auto block_top_left_corner = rotgen::topLeftCorner(matrix); auto block_top_right_corner = rotgen::topRightCorner(matrix); auto block_bottom_left_corner = rotgen::bottomLeftCorner(matrix); auto block_bottom_right_corner = rotgen::bottomRightCorner(matrix); auto block_top_rows = rotgen::topRows(matrix); auto block_middle_rows = rotgen::middleRows(matrix, matrix_construct.i0); auto block_bottom_rows = rotgen::bottomRows(matrix); auto block_left_cols = rotgen::leftCols(matrix); auto block_middle_cols = rotgen::middleCols(matrix, matrix_construct.j0); auto block_right_cols = rotgen::rightCols(matrix); auto block_row = rotgen::row(matrix, matrix_construct.i0); auto block_col = rotgen::col(matrix, matrix_construct.j0); auto blocks = std::make_tuple( std::make_tuple(block_main, matrix_construct.i0, matrix_construct.j0, matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), std::make_tuple(block_top_left_corner, 0, 0, matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), std::make_tuple(block_top_right_corner, 0, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), std::make_tuple(block_bottom_left_corner, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), std::make_tuple(block_bottom_right_corner, matrix.rows() - matrix_construct.ni, matrix.cols() - matrix_construct.nj, matrix_construct.ni, matrix_construct.nj, int(NI), int(NJ), -1), std::make_tuple(block_top_rows, 0, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1), std::make_tuple(block_middle_rows, matrix_construct.i0, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1), std::make_tuple(block_bottom_rows, matrix.rows() - matrix_construct.ni, 0, matrix_construct.ni, matrix.cols(), int(NI), rotgen::Dynamic, -1), std::make_tuple(block_left_cols, 0, 0, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1), std::make_tuple(block_middle_cols, 0, matrix_construct.j0, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1), std::make_tuple(block_right_cols, 0, matrix.cols() - matrix_construct.nj, matrix.rows(), matrix_construct.nj, rotgen::Dynamic, int(NJ), -1), std::make_tuple(block_row, matrix_construct.i0, 0, 1, matrix.cols(), 1, rotgen::Dynamic, 1), std::make_tuple(block_col, 0, matrix_construct.j0, matrix.rows(), 1, rotgen::Dynamic, 1, 0) ); std::apply([&](auto&&... block_entries) { (([&] { auto&& [block, i_offset, j_offset, ni, nj, rows_ct, cols_ct, storage_order] = block_entries; using block_t = std::remove_reference_t; TTS_EQUAL(block_t::RowsAtCompileTime, rows_ct); TTS_EQUAL(block_t::ColsAtCompileTime, cols_ct); auto expected_storage_order = (storage_order == -1) ? MatrixType::storage_order : storage_order; TTS_EQUAL(block_t::storage_order, expected_storage_order); validate_block_behavior(matrix, block, i_offset, j_offset, ni, nj); })(), ...); }, blocks); } TTS_CASE_TPL("Check all dynamic block extractions on a dynamic row-major matrix", rotgen::tests::types) ( tts::type< tts::types> ) { using mat_t = rotgen::matrix; std::vector> cases = { { 6, 11, [](rotgen::Index i, rotgen::Index j) { return T(i * 10 + j); }, 1, 2, 3, 2 }, { 7, 10, [](rotgen::Index i, rotgen::Index j) { return T(std::sin(i + j)); }, 4, 4, 3, 3 }, { 5, 5, [](rotgen::Index i, rotgen::Index j) { return T((i + j) % 7); }, 0, 0, 5, 5 }, { 9, 14, [](rotgen::Index i, rotgen::Index j) { return T(i+j + 3*j); }, 3, 7, 1, 1 } }; for (auto const& matrix_case : cases) { test_dynamic_block_extraction(matrix_case); } }; TTS_CASE_TPL("Check all dynamic block extractions on a static column-major matrix", rotgen::tests::types) ( tts::type< tts::types> ) { using mat_t = rotgen::matrix; std::vector> cases = { { 4, 5, [](auto i, auto j) { return T(2*i + j*j*j - 42); }, 1, 2, 3, 2 }, { 4, 5, [](auto i, auto j) { return T(std::tan(i*i*j)); }, 0, 1, 2, 1 }, { 4, 5, [](auto i, auto j) { return T((i*i + j*j) / 6); }, 2, 0, 0, 0 } }; for (auto const& matrix_case : cases) { test_dynamic_block_extraction(matrix_case); } }; TTS_CASE_TPL("Check all static block extractions", rotgen::tests::types) ( tts::type< tts::types> ) { using mat_t = rotgen::matrix; test_static_block_extraction( rotgen::tests::static_matrix_block_test_case{ 11, 11, [](rotgen::Index i, rotgen::Index j) { return T(i*i*i + 3*j - 127); }, 3, 2 } ); test_static_block_extraction( rotgen::tests::static_matrix_block_test_case{ 14, 15, [](rotgen::Index i, rotgen::Index j) { return T(std::cos(i * j * 2)); }, 5, 1 } ); test_static_block_extraction( rotgen::tests::static_matrix_block_test_case{ 5, 5, [](rotgen::Index i, rotgen::Index j) { return T((i + j) % 9); }, 0, 0 } ); };