| // SPDX-FileCopyrightText: The Eigen Authors |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| #include "main.h" |
| #include <Eigen/LU> |
| |
| using BoundedVector3d = Matrix<double, Dynamic, 1, ColMajor, 3, 1>; |
| using BoundedMatrix3d = Matrix<double, Dynamic, Dynamic, ColMajor, 3, 3>; |
| |
| // Keep the solve result visible to GCC's bounds analysis after inlining dot(). |
| EIGEN_DONT_INLINE BoundedVector3d bounded_update(const BoundedMatrix3d& tangent, const BoundedVector3d& residual, |
| const BoundedMatrix3d& transformation) { |
| const BoundedVector3d increment = tangent.fullPivLu().solve(residual); |
| if (increment.dot(residual) > 0) return transformation * increment; |
| return transformation * residual; |
| } |
| |
| template <typename Scalar, int Capacity> |
| void bounded_inner_products(const Scalar& imaginary_unit = Scalar(0)) { |
| using Bounded = Matrix<Scalar, Dynamic, 1, ColMajor, Capacity, 1>; |
| using DynamicVector = Matrix<Scalar, Dynamic, 1>; |
| using Op = internal::scalar_inner_product_op<Scalar, Scalar, true>; |
| using LeftEvaluator = internal::inner_product_evaluator<Op, Bounded, DynamicVector>; |
| using RightEvaluator = internal::inner_product_evaluator<Op, DynamicVector, Bounded>; |
| STATIC_CHECK(LeftEvaluator::MaxSizeAtCompileTime == Capacity); |
| STATIC_CHECK(RightEvaluator::MaxSizeAtCompileTime == Capacity); |
| for (Index size = 0; size <= Capacity; ++size) { |
| Bounded a(size), b(size); |
| Scalar dot = 0, product = 0; |
| for (Index i = 0; i < size; ++i) { |
| a(i) = Scalar(i % 5 - 2) + imaginary_unit * Scalar(i % 3 - 1); |
| b(i) = Scalar(i % 3 + 1) + imaginary_unit * Scalar(i % 2); |
| dot += numext::conj(a(i)) * b(i); |
| product += a(i) * b(i); |
| } |
| const DynamicVector dynamic = b; |
| VERIFY_IS_EQUAL(a.dot(b), dot); |
| VERIFY_IS_EQUAL(a.dot(dynamic), dot); |
| VERIFY_IS_EQUAL(dynamic.dot(a), numext::conj(dot)); |
| VERIFY_IS_EQUAL(a.transpose().dot(b.transpose()), dot); |
| VERIFY_IS_EQUAL((a.transpose() * b).value(), product); |
| } |
| } |
| |
| EIGEN_DECLARE_TEST(inner_product_bounded) { |
| for (Index size = 1; size <= 3; ++size) { |
| BoundedMatrix3d tangent = BoundedMatrix3d::Identity(size, size); |
| const BoundedMatrix3d transformation = BoundedMatrix3d::Identity(size, size); |
| BoundedVector3d residual(size); |
| for (Index i = 0; i < size; ++i) tangent(i, i) = residual(i) = double(i + 2); |
| VERIFY_IS_EQUAL(bounded_update(tangent, residual, transformation), BoundedVector3d::Ones(size)); |
| tangent = -tangent; |
| VERIFY_IS_EQUAL(bounded_update(tangent, residual, transformation), residual); |
| } |
| bounded_inner_products<double, 3>(); |
| bounded_inner_products<double, 5>(); |
| bounded_inner_products<double, 7>(); |
| bounded_inner_products<double, 17>(); |
| constexpr int packet_size = internal::packet_traits<double>::size; |
| bounded_inner_products<double, 5 * packet_size + 1>(); |
| bounded_inner_products<double, 6 * packet_size + 1>(); |
| bounded_inner_products<double, 7 * packet_size + 1>(); |
| bounded_inner_products<float, 3>(); |
| bounded_inner_products<float, 7>(); |
| bounded_inner_products<float, 15>(); |
| bounded_inner_products<float, 33>(); |
| bounded_inner_products<std::complex<double>, 9>(std::complex<double>(0, 1)); |
| } |