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

View file

@ -0,0 +1,97 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/block.hpp>
#include <rotgen/matrix.hpp>
#include <rotgen/extract.hpp>
#include <Eigen/Dense>
template<typename Block1, typename Block2>
void compare_reductions(const Block1& block, const Block2& ref)
{
constexpr double epsilon = 0.0001;
TTS_RELATIVE_EQUAL(block.sum(), ref.sum(), epsilon);
TTS_RELATIVE_EQUAL(block.prod(), ref.prod(), epsilon);
TTS_RELATIVE_EQUAL(block.mean(), ref.mean(), epsilon);
TTS_EQUAL(block.trace(), ref.trace());
TTS_EQUAL(block.minCoeff(), ref.minCoeff());
TTS_EQUAL(block.maxCoeff(), ref.maxCoeff());
std::ptrdiff_t row, col, ref_row, ref_col;
TTS_EQUAL(block.minCoeff(&row, &col), ref.minCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
TTS_EQUAL(block.maxCoeff(&row, &col), ref.maxCoeff(&ref_row, &ref_col));
TTS_EQUAL(row, ref_row);
TTS_EQUAL(col, ref_col);
}
template <typename MatrixType, typename T>
void test_dynamic_block_reductions(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct)
{
using EigenMatrix = Eigen::Matrix<typename MatrixType::scalar_type, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType original(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref(matrix_construct.rows, matrix_construct.cols);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
ref(r, c) = original(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
std::vector<std::pair<rotgen::block<MatrixType>, Eigen::Block<EigenMatrix>>> test_cases {
{ rotgen::extract(original, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj),
ref.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj) },
{ rotgen::topLeftCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.topLeftCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::topRightCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.topRightCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::bottomLeftCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.bottomLeftCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::bottomRightCorner(original, matrix_construct.ni, matrix_construct.nj),
ref.bottomRightCorner(matrix_construct.ni, matrix_construct.nj) },
{ rotgen::topRows(original, matrix_construct.ni),
ref.topRows(matrix_construct.ni) },
{ rotgen::middleRows(original, matrix_construct.i0, matrix_construct.ni),
ref.middleRows(matrix_construct.i0, matrix_construct.ni) },
{ rotgen::bottomRows(original, matrix_construct.ni),
ref.bottomRows(matrix_construct.ni) },
};
for (const auto& [original_block, ref_block] : test_cases)
compare_reductions(original_block, ref_block);
}
TTS_CASE_TPL("Test dynamic block reductions", 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>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> test_cases =
{
{6, 5, [](auto r, auto c) {return r + c; }, 1, 2, 3, 2},
{9, 11, [](auto r, auto c) {return r + c; }, 0, 1, 4, 9},
{3, 3, [](auto , auto ) {return 0.0; }, 1, 1, 1, 1},
{1, 4, [](auto r, auto c) {return -r -c*c - 1234; }, 0, 0, 1, 1},
{4, 1, [](auto , auto ) {return 7.0; }, 2, 0, 2, 1},
{1, 1, [](auto , auto ) {return 42.0; }, 0, 0, 1, 1},
{12, 13, [](auto r, auto c) {return std::sin(r + c); }, 2, 3, 4, 5 },
{4, 9, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 },
{2, 5, [](auto r, auto c) {return (r == c ? 1.0 : 0.0); }, 1, 1, 1, 1},
};
for (const auto& test_case : test_cases)
test_dynamic_block_reductions<mat_t, T>(test_case);
};

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
}
);
};

49
test/unit/block/norms.cpp Normal file
View file

@ -0,0 +1,49 @@
//==================================================================================================
/*
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>
#include <Eigen/Dense>
TTS_CASE_TPL("Matrix norm-related operations", 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>;
std::vector<rotgen::tests::matrix_block_test_case<mat_t>> test_cases =
{
{6, 5, [](auto r, auto c) {return r + c; }, 1, 2, 3, 2},
{9, 11, [](auto r, auto c) {return r + c; }, 0, 1, 4, 9},
{3, 3, [](auto , auto ) {return 0.0; }, 1, 1, 1, 1},
{1, 4, [](auto r, auto c) {return -r -c*c - 1234; }, 0, 0, 1, 1},
{4, 1, [](auto , auto ) {return 7.0; }, 2, 0, 2, 1},
{1, 1, [](auto , auto ) {return 42.0; }, 0, 0, 1, 1},
{12, 13, [](auto r, auto c) {return std::sin(r + c); }, 2, 3, 4, 5 },
{4, 9, [](auto r, auto c) {return -1.5 * r + 2.56 * c; }, 0, 1, 2, 3 },
{2, 5, [](auto r, auto c) {return (r == c ? 1.0 : 0.0); }, 1, 1, 1, 1},
};
for (const auto& [rows, cols, fn, i0, j0, ni, nj] : test_cases)
{
rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic,O::value> original_matrix(rows, cols);
Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic,O::value> ref_matrix(rows, cols);
for (std::size_t r = 0; r < rows; ++r)
for (std::size_t c = 0; c < cols; ++c)
ref_matrix(r, c) = original_matrix(r, c) = fn(r,c);
auto original_block = rotgen::extract(original_matrix, i0, j0, ni, nj);
auto ref_block = ref_matrix.block(i0, j0, ni, nj);
TTS_EQUAL(original_block.norm(), ref_block.norm());
TTS_EQUAL(original_block.squaredNorm(), ref_block.squaredNorm());
TTS_EQUAL(original_block.template lpNorm<1>() , ref_block.template lpNorm<1>());
TTS_EQUAL(original_block.template lpNorm<2>() , ref_block.template lpNorm<2>());
TTS_EQUAL(original_block.template lpNorm<rotgen::Infinity>(), ref_block.template lpNorm<Eigen::Infinity>());
}
};

View file

@ -0,0 +1,274 @@
//==================================================================================================
/*
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>
#include <Eigen/Dense>
template <typename MatrixType, typename T>
void test_block_matrix_operations(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
auto b_init_fn, auto self_ops)
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(matrix_construct.rows, matrix_construct.cols);
MatrixType b(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_b(matrix_construct.rows, matrix_construct.cols);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
{
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
{
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
ref_b(r,c) = b(r,c) = static_cast<T>(b_init_fn(r, c));
}
}
auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto b_block = rotgen::extract(b, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_b_block = ref_b.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
/*auto result_block = ops(a_block, b_block);
auto ref_result_block = ops(ref_a_block, ref_b_block);
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(result_block(r, c), ref_result_block(r, c));*/
self_ops(a_block,b_block);
self_ops(ref_a_block, ref_b_block);
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
{
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
{
TTS_EQUAL(a(r, c), ref_a(r, c));
TTS_EQUAL(b(r, c), ref_b(r, c));
}
}
}
template <typename MatrixType, typename T>
void test_block_scalar_operations(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
auto scalar, auto self_ops)
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
//TTS_EQUAL(ops(a, s), ref);
self_ops(a_block,scalar);
self_ops(ref_a_block, scalar);
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
}
template <typename MatrixType, typename T>
void test_scalar_block_multiplications(rotgen::tests::matrix_block_test_case<MatrixType> const& matrix_construct,
T scalar)
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(matrix_construct.rows, matrix_construct.cols);
EigenMatrix ref_a(matrix_construct.rows, matrix_construct.cols);
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(matrix_construct.init_fn(r, c));
auto a_block = rotgen::extract(a, matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
auto ref_a_block = ref_a.block(matrix_construct.i0, matrix_construct.j0,
matrix_construct.ni, matrix_construct.nj);
//TTS_EQUAL(a * s, ref);
//TTS_EQUAL(s * a, ref);
a_block *= scalar;
ref_a_block *= scalar;
for (std::size_t r = 0; r < matrix_construct.ni; ++r)
for (std::size_t c = 0; c < matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < matrix_construct.rows; ++r)
for (std::size_t c = 0; c < matrix_construct.cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
}
template <typename MatrixType, typename T>
void test_block_multiplication(rotgen::tests::matrix_block_test_case<MatrixType> const& a_matrix_construct,
rotgen::tests::matrix_block_test_case<MatrixType> const& b_matrix_construct)
{
using EigenMatrix = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType a(a_matrix_construct.rows, a_matrix_construct.cols);
MatrixType b(b_matrix_construct.rows, b_matrix_construct.cols);
EigenMatrix ref_a(a_matrix_construct.rows, a_matrix_construct.cols);
EigenMatrix ref_b(b_matrix_construct.rows, b_matrix_construct.cols);
for (std::size_t r = 0; r < a_matrix_construct.rows; ++r)
for (std::size_t c = 0; c < a_matrix_construct.cols; ++c)
ref_a(r,c) = a(r,c) = static_cast<T>(a_matrix_construct.init_fn(r, c));
for (std::size_t r = 0; r < b_matrix_construct.rows; ++r)
for (std::size_t c = 0; c < b_matrix_construct.cols; ++c)
ref_b(r,c) = b(r,c) = static_cast<T>(b_matrix_construct.init_fn(r, c));
auto a_block = rotgen::extract(a, a_matrix_construct.i0, a_matrix_construct.j0,
a_matrix_construct.ni, a_matrix_construct.nj);
auto b_block = rotgen::extract(b, b_matrix_construct.i0, b_matrix_construct.j0,
b_matrix_construct.ni, b_matrix_construct.nj);
auto ref_a_block = ref_a.block(a_matrix_construct.i0, a_matrix_construct.j0,
a_matrix_construct.ni, a_matrix_construct.nj);
auto ref_b_block = ref_b.block(b_matrix_construct.i0, b_matrix_construct.j0,
b_matrix_construct.ni, b_matrix_construct.nj);
// a * b
a_block *= b_block;
ref_a_block *= ref_b_block;
for (std::size_t r = 0; r < a_matrix_construct.ni; ++r)
for (std::size_t c = 0; c < a_matrix_construct.nj; ++c)
TTS_EQUAL(a_block(r, c), ref_a_block(r, c));
for (std::size_t r = 0; r < a_matrix_construct.rows; ++r)
for (std::size_t c = 0; c < a_matrix_construct.cols; ++c)
TTS_EQUAL(a(r, c), ref_a(r, c));
for (std::size_t r = 0; r < b_matrix_construct.rows; ++r)
for (std::size_t c = 0; c < b_matrix_construct.cols; ++c)
TTS_EQUAL(b(r, c), ref_b(r, c));
}
// Basic initializers
inline constexpr auto init_a = [](auto r, auto c) { return 9.9*r*r*r - 6*c -12; };
inline constexpr auto init_b = [](auto r, auto c) { return 3.1*r + 4.2*c - 12.3; };
inline constexpr auto init_0 = [](auto , auto ) { return 0; };
TTS_CASE_TPL("Check block addition", 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>;
//auto op = [](auto a, auto b) { return a + b; };
auto s_op = [](auto& a, auto b) { return a += b; };
//test_block_matrix_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, init_b, op, s_op);
test_block_matrix_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, init_a, s_op);
test_block_matrix_operations<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, init_0, s_op);
};
TTS_CASE_TPL("Check block subtraction", 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>;
//auto op = [](auto a, auto b) { return a - b; };
auto s_op = [](auto& a, auto b) { return a -= b; };
//test_block_matrix_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, init_b, op, s_op);
test_block_matrix_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, init_a, s_op);
test_block_matrix_operations<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, init_b,s_op);
test_block_matrix_operations<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, init_b, s_op);
test_block_matrix_operations<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, init_0, s_op);
};
TTS_CASE_TPL("Check block multiplications", 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>;
auto init_id = [](auto r, auto c) { return r == c ? 1 : 0; };
test_block_multiplication<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, {1 , 1, init_b, 0, 0, 1, 1});
test_block_multiplication<mat_t, T>({13 , 15, init_b, 1, 2, 4, 4}, {13 , 15, init_b, 0, 1, 4, 4});
test_block_multiplication<mat_t, T>({6 , 9, init_a, 2, 2, 2, 2}, {5 , 9, init_b, 2, 2, 2, 2});
test_block_multiplication<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, {15 , 15, init_b, 0, 0, 5, 5});
test_block_multiplication<mat_t, T>({5 , 5, init_b, 1, 0, 3, 3}, {5 , 5, init_a, 0, 0, 3, 3});
test_block_multiplication<mat_t, T>({11 , 3, init_id, 2, 0, 2, 2}, {18 , 7, init_a, 2, 0, 2, 2});
test_block_multiplication<mat_t, T>({10, 1, init_a, 0, 0, 1, 1}, {10, 1, init_a, 0, 0, 1, 1});
test_block_multiplication<mat_t, T>({1 , 10, init_a, 0, 0, 1, 1}, {1 , 10, init_id, 0, 0, 1, 1});
test_block_multiplication<mat_t, T>({21 , 5, init_0, 1, 1, 3, 3}, {12 , 7, init_0, 4, 4, 3, 3});
test_block_multiplication<mat_t, T>({11 , 7, init_a, 2, 0, 7, 7}, {11 , 11, init_a, 2, 1, 7, 7});
test_block_multiplication<mat_t, T>({11 , 7, init_a, 2, 0, 5, 5}, {11 , 12, init_id, 0, 0, 5, 5});
};
TTS_CASE_TPL("Check block multiplication with scalar", 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>;
test_scalar_block_multiplications<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5});
test_scalar_block_multiplications<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, T{ 0.});
test_scalar_block_multiplications<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, T{-2.5});
test_scalar_block_multiplications<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, T{ 42. });
test_scalar_block_multiplications<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, T{-5. });
test_scalar_block_multiplications<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, T{ 1. });
test_scalar_block_multiplications<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, T{ 6. });
test_scalar_block_multiplications<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, T{ 10.1});
test_scalar_block_multiplications<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, T{-0.5});
};
TTS_CASE_TPL("Check block division with scalar", 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>;
//auto op = [](auto a, auto b) { return a / b; };
auto s_op = [](auto& a, auto b) { return a /= b; };
//test_block_scalar_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}, op, s_op);
test_block_scalar_operations<mat_t, T>({1 , 1, init_a, 0, 0, 1, 1}, T{ 3.5}, s_op);
test_block_scalar_operations<mat_t, T>({13 , 15, init_a, 1, 2, 3, 4}, T{-2.5}, s_op);
test_block_scalar_operations<mat_t, T>({5 , 9, init_a, 2, 2, 2, 2}, T{ 42. }, s_op);
test_block_scalar_operations<mat_t, T>({15 , 15, init_a, 3, 4, 5, 5}, T{-5. }, s_op);
test_block_scalar_operations<mat_t, T>({5 , 5, init_b, 1, 0, 3, 2}, T{ 1. }, s_op);
test_block_scalar_operations<mat_t, T>({10, 1, init_a, 0, 0, 5, 1}, T{ 0. }, s_op);
test_block_scalar_operations<mat_t, T>({1 , 10, init_a, 0, 0, 1, 5}, T{ 6. },s_op);
test_block_scalar_operations<mat_t, T>({21 , 5, init_0, 4, 4, 10, 1}, T{ 10.}, s_op);
test_block_scalar_operations<mat_t, T>({11 , 7, init_a, 2, 0, 7, 5}, T{-0.5}, s_op);
};

View file

@ -0,0 +1,115 @@
//==================================================================================================
/*
ROTGEN - Runtime Overlay for Eigen
Copyright : CODE RECKONS
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#include "unit/tests.hpp"
#include <rotgen/block.hpp>
#include <rotgen/matrix.hpp>
void test_size(const auto& matrix, std::size_t rows, std::size_t cols)
{
TTS_EQUAL(matrix.rows(), rows);
TTS_EQUAL(matrix.cols(), cols);
TTS_EQUAL(matrix.size(), rows*cols);
}
void test_value(const auto& matrix, std::size_t rows, std::size_t cols, auto constant)
{
test_size(matrix, rows, cols);
for(std::size_t r=0;r<rows;++r)
for(std::size_t c=0;c<cols;++c)
TTS_EQUAL(matrix(r, c), constant);
}
void test_random(const auto& matrix, std::size_t rows, std::size_t cols)
{
test_size(matrix, rows, cols);
for(std::size_t r=0;r<rows;++r)
for(std::size_t c=0;c<cols;++c)
{
TTS_GREATER_EQUAL(matrix(r, c), -1.0);
TTS_LESS_EQUAL(matrix(r, c), 1.0);
}
}
void test_identity(const auto& matrix, std::size_t rows, std::size_t cols)
{
test_size(matrix, rows, cols);
for(std::size_t r=0;r<rows;++r)
for(std::size_t c=0;c<cols;++c)
TTS_EQUAL(matrix(r, c), r==c ? 1 : 0);
}
TTS_CASE_TPL("Test zero", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>>)
{
test_value(rotgen::block<rotgen::matrix<T, 7, 8>, 3, 4>::Zero(), 3, 4, 0);
test_value(rotgen::block<rotgen::matrix<T, 72, 2>, 1, 1>::Zero(), 1, 1, 0);
test_value(rotgen::block<rotgen::matrix<T, 21, 33>, 10, 10>::Zero(), 10, 10, 0);
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 4>::Zero(3, 4), 3, 4, 0);
test_value(rotgen::block<rotgen::matrix<T, 17, 4>, 3, 3>::Zero(3, 3), 3, 3, 0);
test_value(rotgen::block<rotgen::matrix<T, 2, 2>, 2, 2>::Zero(2, 2), 2, 2, 0);
test_value(rotgen::block<rotgen::matrix<T, 8, 7>, rotgen::Dynamic, rotgen::Dynamic>::Zero(2, 3), 2, 3, 0);
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, 0, 0>::Zero(0, 0), 0, 0, 0);
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(2, 7)),
rotgen::Dynamic, 7>::Zero(3, 7), 3, 7, 0);
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 3)),
4, rotgen::Dynamic>::Zero(4, 3), 4, 3, 0);
};
TTS_CASE_TPL("Test constant", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 4>::Constant(5.12), 3, 4, T(5.12));
test_value(rotgen::block<rotgen::matrix<T, 88, 81>, 1, 1>::Constant(2.2), 1, 1, T(2.2));
test_value(rotgen::block<rotgen::matrix<T, 21, 33>, 10, 10>::Constant(13), 10, 10, T(13));
test_value(rotgen::block<rotgen::matrix<T, 3, 4>, rotgen::Dynamic, rotgen::Dynamic>::Constant(2, 7, 5.6), 2, 7, T(5.6));
test_value(rotgen::block<rotgen::matrix<T, 17, 5>, 2, 2>::Constant(2, 2, 2.0), 2, 2, T(2.0));
test_value(rotgen::block<rotgen::matrix<T, 144, 109>, rotgen::Dynamic, 9>::Constant(9, 9, 1.1), 9, 9, T(1.1));
test_value(rotgen::block<rotgen::matrix<T, 8, 11>, 5, rotgen::Dynamic>::Constant(5, 9, 42), 5, 9, T(42));
test_value(rotgen::block<rotgen::matrix<T, 4, 3>, 4, 3>::Constant(4, 3, 0), 4, 3, 0);
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(3, 7)),
rotgen::Dynamic, 7>::Constant(3, 7, 88), 3, 7, T(88));
test_value(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 3)),
4, rotgen::Dynamic>::Constant(4, 3, 3.99), 4, 3, T(3.99));
};
TTS_CASE_TPL("Test random", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_random(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 3>::Random(), 3, 3);
test_random(rotgen::block<rotgen::matrix<T, 1, 1>, 1, 1>::Random(), 1, 1);
test_random(rotgen::block<rotgen::matrix<T, 13, 12>, 3, 4>::Random(), 3, 4);
test_random(rotgen::block<rotgen::matrix<T, 3, 4>, rotgen::Dynamic, rotgen::Dynamic>::Random(1, 5), 1, 5);
test_random(rotgen::block<rotgen::matrix<T, 17, 11>, 2, 1>::Random(2, 1), 2, 1);
test_random(rotgen::block<rotgen::matrix<T, 109, 117>, rotgen::Dynamic, 9>::Random(3, 9), 3, 9);
test_random(rotgen::block<rotgen::matrix<T, 9, 11>, 5, rotgen::Dynamic>::Random(5, 2), 5, 2);
test_random(rotgen::block<rotgen::matrix<T, 4, 3>, 4, 3>::Random(4, 3), 4, 3);
test_random(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(3, 7)),
rotgen::Dynamic, 7>::Random(3, 7), 3, 7);
test_random(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 15)),
4, rotgen::Dynamic>::Random(4, 11), 4, 11);
};
TTS_CASE_TPL("Test identity", rotgen::tests::types)
<typename T, typename O>( tts::type< tts::types<T,O>> )
{
test_identity(rotgen::block<rotgen::matrix<T, 3, 4>, 3, 3>::Identity(), 3, 3);
test_identity(rotgen::block<rotgen::matrix<T, 1, 1>, 1, 1>::Identity(), 1, 1);
test_identity(rotgen::block<rotgen::matrix<T, 13, 12>, 3, 4>::Identity(), 3, 4);
test_identity(rotgen::block<rotgen::matrix<T, 3, 4>, rotgen::Dynamic, rotgen::Dynamic>::Identity(1, 5), 1, 5);
test_identity(rotgen::block<rotgen::matrix<T, 17, 11>, 2, 1>::Identity(2, 1), 2, 1);
test_identity(rotgen::block<rotgen::matrix<T, 109, 117>, rotgen::Dynamic, 9>::Identity(3, 9), 3, 9);
test_identity(rotgen::block<rotgen::matrix<T, 9, 11>, 5, rotgen::Dynamic>::Identity(5, 2), 5, 2);
test_identity(rotgen::block<rotgen::matrix<T, 4, 3>, 4, 3>::Identity(4, 3), 4, 3);
test_identity(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Identity(3, 7)),
rotgen::Dynamic, 7>::Identity(3, 7), 3, 7);
test_identity(rotgen::block<decltype(rotgen::matrix<T,rotgen::Dynamic,rotgen::Dynamic, O::value>::Random(14, 15)),
4, rotgen::Dynamic>::Identity(4, 11), 4, 11);
};

View file

@ -59,7 +59,7 @@ TTS_CASE_TPL("Test transpotion related operations", rotgen::tests::types)
template <typename MatrixType>
void test_matrix_reductions(std::size_t rows, std::size_t cols, auto const& init_fn)
{
using EigenMatrix = Eigen::Matrix<typename MatrixType::value_type, Eigen::Dynamic, Eigen::Dynamic>;
using EigenMatrix = Eigen::Matrix<typename MatrixType::scalar_type, Eigen::Dynamic, Eigen::Dynamic>;
MatrixType original(rows, cols);
EigenMatrix ref(rows, cols);

View file

@ -28,4 +28,22 @@ namespace rotgen::tests
std::size_t rows, cols;
std::function<double(std::size_t,std::size_t)> init_fn;
};
template<typename MatrixType>
struct matrix_block_test_case
{
std::size_t rows, cols;
std::function<typename MatrixType::scalar_type(std::size_t, std::size_t)> init_fn;
std::size_t i0, j0, ni, nj;
};
template<typename MatrixType, std::size_t NI, std::size_t NJ>
struct static_matrix_block_test_case
{
std::size_t rows, cols;
std::function<typename MatrixType::scalar_type(std::size_t, std::size_t)> init_fn;
static constexpr std::size_t ni = NI;
static constexpr std::size_t nj = NJ;
std::size_t i0, j0;
};
}