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