blob: 6a1a9be970d77117e2d808921ca453a0807f5821 [file] [edit]
// 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));
}