Implements block typs and related functions - First part

Co-authored-by: Karen <kkaspar@codereckons.com>
Co-authored-by: Joel FALCOU <jfalcou@codereckons.com>

See merge request oss/rotgen!9
This commit is contained in:
Karen Kaspar 2025-06-12 13:38:31 +02:00 committed by Joel Falcou
parent 09be3b4b15
commit c6b864f247
28 changed files with 1814 additions and 114 deletions

266
test/unit/block/extract.cpp Normal file
View file

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