blob: 59bf5c5a2233081cf3a36e7c2e647c9203fd610a [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include "main.h"
template <typename Dst, typename Src, typename Functor>
void check_block_coeffwise_dispatch() {
#if EIGEN_UNALIGNED_VECTORIZE
using Scalar = typename Dst::Scalar;
using Kernel = internal::generic_dense_assignment_kernel<internal::evaluator<Dst>, internal::evaluator<Src>, Functor>;
using Traits = typename Kernel::AssignmentTraits;
constexpr bool packetSupported = internal::packet_traits<Scalar>::Vectorizable &&
internal::packet_traits<Scalar>::HasMul &&
internal::functor_traits<Functor>::PacketAccess;
STATIC_CHECK(!packetSupported || Traits::Traversal == SliceVectorizedTraversal);
STATIC_CHECK(!packetSupported || Traits::Unrolling == NoUnrolling);
using Loop = internal::dense_assignment_loop_impl<Kernel, SliceVectorizedTraversal, NoUnrolling>;
STATIC_CHECK(!packetSupported || EIGEN_MAX_ALIGN_BYTES < Loop::RequestedAlignment || Loop::DstIsAligned);
#endif
}
template <typename Scalar, int Order>
void block_coeffwise() {
using Mat = Matrix<Scalar, Dynamic, Dynamic, Order>;
using Product = internal::remove_all_t<
decltype(std::declval<const Mat&>().block(0, 0, 0, 0).cwiseProduct(std::declval<const Mat&>()))>;
check_block_coeffwise_dispatch<Mat, Product, internal::assign_op<Scalar, Scalar>>();
check_block_coeffwise_dispatch<Mat, Product, internal::add_assign_op<Scalar, Scalar>>();
check_block_coeffwise_dispatch<Mat, Product, internal::sub_assign_op<Scalar, Scalar>>();
constexpr Index packetSize = internal::packet_traits<Scalar>::size;
for (Index inner = 0; inner <= (std::max)(Index(33), 2 * packetSize + 1); ++inner) {
for (Index offset : {0, 1, 3}) {
const Index rows = Order == ColMajor ? inner : 5;
const Index cols = Order == ColMajor ? 5 : inner;
const Mat src = Mat::Random(rows + 7, cols + 7);
const Mat rhs = Mat::Random(rows, cols);
Mat dst = Mat::Constant(rows + 7, cols + 7, Scalar(3));
Mat expected = dst;
auto block = dst.block(offset, offset, rows, cols);
block.array() = src.block(offset, offset, rows, cols).array() * rhs.array();
for (Index j = 0; j < cols; ++j)
for (Index i = 0; i < rows; ++i) expected(i + offset, j + offset) = src(i + offset, j + offset) * rhs(i, j);
VERIFY_IS_APPROX(dst, expected);
block.array() += src.block(offset, offset, rows, cols).array() * rhs.array();
expected.block(offset, offset, rows, cols) *= Scalar(2);
VERIFY_IS_APPROX(dst, expected);
Mat packed = src.block(offset, offset, rows, cols).cwiseProduct(rhs);
VERIFY_IS_APPROX(packed, (expected.block(offset, offset, rows, cols) / Scalar(2)));
const auto product = src.block(offset, offset, rows, cols).cwiseProduct(rhs);
const Mat initial = Mat::Random(rows, cols);
Mat compound = initial;
Mat reference(rows, cols);
compound += product;
for (Index j = 0; j < cols; ++j)
for (Index i = 0; i < rows; ++i) reference(i, j) = initial(i, j) + src(i + offset, j + offset) * rhs(i, j);
VERIFY_IS_APPROX(compound, reference);
compound = initial;
compound -= product;
for (Index j = 0; j < cols; ++j)
for (Index i = 0; i < rows; ++i) reference(i, j) = initial(i, j) - src(i + offset, j + offset) * rhs(i, j);
VERIFY_IS_APPROX(compound, reference);
}
}
}
EIGEN_DECLARE_TEST(block_coeffwise) {
CALL_SUBTEST((block_coeffwise<float, ColMajor>()));
CALL_SUBTEST((block_coeffwise<float, RowMajor>()));
CALL_SUBTEST((block_coeffwise<double, ColMajor>()));
CALL_SUBTEST((block_coeffwise<double, RowMajor>()));
CALL_SUBTEST((block_coeffwise<std::complex<float>, ColMajor>()));
CALL_SUBTEST((block_coeffwise<std::complex<float>, RowMajor>()));
}