blob: c44670266945d5e889e684fc9cdb96da90036994 [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include "main.h"
using BoundedVector4d = Matrix<double, Dynamic, 1, ColMajor, 4, 1>;
using BoundedMatrix4d = Matrix<double, Dynamic, Dynamic, ColMajor, 4, 4>;
EIGEN_DONT_INLINE MatrixXd bounded_transform(const MatrixXd& vertices, const BoundedMatrix4d& transform) {
MatrixXd transformed(vertices.rows(), vertices.cols());
for (Index col = 0; col < vertices.cols(); ++col) {
BoundedVector4d homogeneous = BoundedVector4d::Ones(vertices.rows() + 1);
homogeneous.head(vertices.rows()) = vertices.col(col);
transformed.col(col) = (transform * homogeneous).head(vertices.rows());
}
return transformed;
}
struct BoundedFirst {
int operator()(int first, int) const { return first; }
};
template <int Order>
void mixed_bounded_products() {
using BoundedVector = Matrix<double, Dynamic, 1, ColMajor, 3, 1>;
using DynamicMatrix = Matrix<double, Dynamic, Dynamic, Order>;
for (Index size = 1; size <= 3; ++size) {
const DynamicMatrix matrix = DynamicMatrix::Random(size, size);
const BoundedVector vector = BoundedVector::Random(size);
const VectorXd dynamic = vector;
const auto left = dynamic.cwiseProduct(vector);
const auto right = vector.cwiseProduct(dynamic);
STATIC_CHECK(decltype(left)::MaxSizeAtCompileTime == Dynamic);
STATIC_CHECK(decltype(right)::MaxSizeAtCompileTime == 3);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(left)>>::Size == 3);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(right)>>::Size == 3);
VERIFY_IS_EQUAL(left.sum(), right.sum());
const BoundedVector result = matrix * vector;
const auto reversed = (vector.transpose() * matrix.transpose()).eval();
for (Index row = 0; row < size; ++row) {
double expected = 0;
for (Index col = 0; col < size; ++col) expected += matrix(row, col) * vector(col);
VERIFY(numext::abs(result(row) - expected) <= 8 * NumTraits<double>::epsilon());
VERIFY(numext::abs(reversed(row) - expected) <= 8 * NumTraits<double>::epsilon());
}
}
}
template <int Order>
void heap_backed_expression_bounds() {
using RowsBounded = Matrix<double, Dynamic, Dynamic, Order, 200, Dynamic>;
using ColsBounded = Matrix<double, Dynamic, Dynamic, Order, Dynamic, 200>;
const RowsBounded a = RowsBounded::Ones(2, 2);
const ColsBounded b = ColsBounded::Ones(2, 2);
using Bounds = internal::redux_max_size<internal::remove_all_t<decltype(a + b)>>;
STATIC_CHECK(Bounds::Rows == 200);
STATIC_CHECK(Bounds::Cols == 200);
STATIC_CHECK(Bounds::Size == 40000);
const auto sum = (a + b).eval();
const auto reversed = (b + a).eval();
STATIC_CHECK((std::is_same<internal::remove_all_t<decltype(sum)>, RowsBounded>::value));
STATIC_CHECK((std::is_same<internal::remove_all_t<decltype(reversed)>, ColsBounded>::value));
VERIFY_IS_EQUAL(sum, RowsBounded::Constant(2, 2, 2));
VERIFY_IS_EQUAL(reversed, ColsBounded::Constant(2, 2, 2));
VERIFY_IS_EQUAL((a + b).sum(), 8);
}
template <int Order>
void complementary_reduction_bounds() {
using RowsBounded = Matrix<int, Dynamic, Dynamic, Order, 4, Dynamic>;
using ColsBounded = Matrix<int, Dynamic, Dynamic, Order, Dynamic, 4>;
const RowsBounded a = RowsBounded::Constant(3, 4, 2);
const ColsBounded b = ColsBounded::Constant(3, 4, 3);
using Bounds = internal::redux_max_size<internal::remove_all_t<decltype(a + b)>>;
STATIC_CHECK(Bounds::Size == 16);
VERIFY_IS_EQUAL((a + b).sum(), 60);
VERIFY_IS_EQUAL((a + b).redux(BoundedFirst()), 5);
VERIFY_IS_EQUAL((b + a).redux(BoundedFirst()), 5);
const auto wrapped_array = (a + b).array();
const auto wrapped_matrix = (a.array() + b.array()).matrix();
using ArrayBounds = internal::redux_max_size<internal::remove_all_t<decltype(wrapped_array)>>;
using MatrixBounds = internal::redux_max_size<internal::remove_all_t<decltype(wrapped_matrix)>>;
STATIC_CHECK(ArrayBounds::Rows == 4 && ArrayBounds::Cols == 4 && ArrayBounds::Size == 16);
STATIC_CHECK(MatrixBounds::Rows == 4 && MatrixBounds::Cols == 4 && MatrixBounds::Size == 16);
STATIC_CHECK(decltype(wrapped_array)::MaxSizeAtCompileTime == Dynamic);
STATIC_CHECK(decltype(wrapped_matrix)::MaxSizeAtCompileTime == Dynamic);
VERIFY_IS_EQUAL(wrapped_array.sum(), 60);
VERIFY_IS_EQUAL(wrapped_matrix.sum(), 60);
VERIFY_IS_EQUAL(wrapped_array.redux(BoundedFirst()), 5);
VERIFY_IS_EQUAL(wrapped_matrix.redux(BoundedFirst()), 5);
const Matrix<bool, Dynamic, Dynamic, Order> condition = Matrix<bool, Dynamic, Dynamic, Order>::Constant(3, 4, true);
const auto selected = condition.select(a, b);
const auto reversed = condition.select(b, a);
using SelectedBounds = internal::redux_max_size<internal::remove_all_t<decltype(selected)>>;
using ReversedBounds = internal::redux_max_size<internal::remove_all_t<decltype(reversed)>>;
STATIC_CHECK(SelectedBounds::Rows == 4 && SelectedBounds::Cols == 4 && SelectedBounds::Size == 16);
STATIC_CHECK(ReversedBounds::Size == 16);
STATIC_CHECK(decltype(selected)::MaxSizeAtCompileTime == Dynamic);
VERIFY_IS_EQUAL(selected.sum(), 24);
VERIFY_IS_EQUAL(reversed.sum(), 36);
VERIFY_IS_EQUAL(selected.redux(BoundedFirst()), 2);
VERIFY_IS_EQUAL(reversed.redux(BoundedFirst()), 3);
using Bounded = Matrix<int, Dynamic, Dynamic, Order, 4, 4>;
const Bounded bounded = Bounded::Constant(3, 4, 7);
const Matrix<int, Dynamic, Dynamic, Order> dynamic = bounded;
const auto bounded_second = condition.select(bounded, dynamic);
const auto bounded_third = condition.select(dynamic, bounded);
const auto bounded_first = (bounded.array() > 0).select(dynamic.array(), dynamic.array());
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(bounded_second)>>::Size == 16);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(bounded_third)>>::Size == 16);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(bounded_first)>>::Size == 16);
VERIFY_IS_EQUAL(bounded_second.sum(), 84);
VERIFY_IS_EQUAL(bounded_third.sum(), 84);
VERIFY_IS_EQUAL(bounded_first.sum(), 84);
using HugeRows = Matrix<int, Dynamic, Dynamic, Order, 100000, Dynamic>;
using HugeCols = Matrix<int, Dynamic, Dynamic, Order, Dynamic, 100000>;
using HugeExpression = decltype(std::declval<HugeRows>() + std::declval<HugeCols>());
STATIC_CHECK(internal::redux_max_size<HugeExpression>::Size == Dynamic);
}
template <typename Scalar, int Capacity>
void mixed_packet_reductions() {
using Bounded = Matrix<Scalar, Dynamic, 1, ColMajor, Capacity, 1>;
using DynamicVector = Matrix<Scalar, Dynamic, 1>;
for (Index size = 0; size <= Capacity; ++size) {
Bounded bounded(size);
DynamicVector dynamic(size);
Scalar expected = 0;
for (Index i = 0; i < size; ++i) {
bounded(i) = Scalar(i % 5 - 2);
dynamic(i) = Scalar(i % 3 + 1);
expected += bounded(i) * dynamic(i);
}
const auto left = dynamic.cwiseProduct(bounded);
const auto right = bounded.cwiseProduct(dynamic);
STATIC_CHECK(decltype(left)::MaxSizeAtCompileTime == Dynamic);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(left)>>::Size == Capacity);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(right)>>::Size == Capacity);
VERIFY_IS_EQUAL(left.sum(), expected);
VERIFY_IS_EQUAL(right.sum(), expected);
const auto squared = left.cwiseAbs2();
const auto negated = -squared;
STATIC_CHECK(decltype(squared)::MaxSizeAtCompileTime == Dynamic);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(squared)>>::Size == Capacity);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(negated)>>::Size == Capacity);
Scalar expectedSquared = 0;
for (Index i = 0; i < size; ++i) {
const Scalar value = bounded(i) * dynamic(i);
expectedSquared += value * value;
}
VERIFY_IS_EQUAL(squared.sum(), expectedSquared);
VERIFY_IS_EQUAL(negated.sum(), -expectedSquared);
VERIFY_IS_EQUAL(left.squaredNorm(), expectedSquared);
const auto wrapped = left.array().square();
auto array_product = dynamic.array() * bounded.array();
const auto matrix = array_product.matrix();
const auto nested = matrix.array().square().matrix();
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(wrapped)>>::Size == Capacity);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(matrix)>>::Size == Capacity);
STATIC_CHECK(internal::redux_max_size<internal::remove_all_t<decltype(nested)>>::Size == Capacity);
VERIFY_IS_EQUAL(wrapped.sum(), expectedSquared);
VERIFY_IS_EQUAL(matrix.sum(), expected);
VERIFY_IS_EQUAL(matrix.squaredNorm(), expectedSquared);
VERIFY_IS_EQUAL(nested.sum(), expectedSquared);
}
}
template <int Order>
void bounded_reductions() {
for (Index size : {1, 4, 15, 16, 31, 32, 33, 64}) {
Matrix<int, Dynamic, Dynamic, Order, 64, 64> matrix(size, size);
for (Index row = 0; row < size; ++row)
for (Index col = 0; col < size; ++col) matrix(row, col) = int(row + col + 1);
VERIFY_IS_EQUAL(matrix.sum(), size * size * size);
VERIFY_IS_EQUAL(matrix.redux(BoundedFirst()), 1);
VERIFY_IS_EQUAL(matrix.topLeftCorner(size, size).sum(), size * size * size);
VERIFY_IS_EQUAL(matrix.topLeftCorner(size, size).redux(BoundedFirst()), 1);
}
}
EIGEN_DECLARE_TEST(redux_bounded) {
mixed_packet_reductions<float, 3>();
mixed_packet_reductions<float, 7>();
mixed_packet_reductions<float, 15>();
mixed_packet_reductions<float, 17>();
mixed_packet_reductions<double, 3>();
mixed_packet_reductions<double, 7>();
mixed_packet_reductions<double, 15>();
mixed_packet_reductions<double, 17>();
for (Index size = 0; size <= 3; ++size) {
const MatrixXd vertices = MatrixXd::Random(size, 10);
const BoundedMatrix4d transform = BoundedMatrix4d::Random(size + 1, size + 1);
const MatrixXd result = bounded_transform(vertices, transform);
for (Index row = 0; row < size; ++row) {
for (Index col = 0; col < vertices.cols(); ++col) {
double expected = transform(row, size);
for (Index k = 0; k < size; ++k) expected += transform(row, k) * vertices(k, col);
VERIFY(numext::abs(result(row, col) - expected) <= 32 * NumTraits<double>::epsilon());
}
}
}
bounded_reductions<ColMajor>();
bounded_reductions<RowMajor>();
mixed_bounded_products<ColMajor>();
mixed_bounded_products<RowMajor>();
heap_backed_expression_bounds<ColMajor>();
heap_backed_expression_bounds<RowMajor>();
complementary_reduction_bounds<ColMajor>();
complementary_reduction_bounds<RowMajor>();
}