| // SPDX-FileCopyrightText: The Eigen Authors | |
| // SPDX-License-Identifier: MPL-2.0 | |
| #include <Eigen/Core> | |
| #include <functional> | |
| // Scalar only: InnerProduct's packet-enabled unit-stride remap loses this product's bound. | |
| #ifdef EIGEN_DONT_VECTORIZE | |
| using BoundedVector4d = Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::ColMajor, 4, 1>; | |
| using BoundedMatrix4d = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor, 4, 4>; | |
| Eigen::MatrixXd bounded_transform(const Eigen::MatrixXd& vertices, const BoundedMatrix4d& transform) { | |
| Eigen::MatrixXd transformed(vertices.rows(), vertices.cols()); | |
| for (Eigen::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; | |
| } | |
| #endif | |
| using BoundedVector3d = Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::ColMajor, 3, 1>; | |
| std::function<Eigen::VectorXd(Eigen::Index)> evaluate_position; | |
| template <int Mode> | |
| EIGEN_ALWAYS_INLINE double bounded_residual(const BoundedVector3d& target, Eigen::Index size) { | |
| const Eigen::VectorXd position = evaluate_position(size); | |
| EIGEN_IF_CONSTEXPR (Mode == 0) { | |
| return (position - target.head(size)).norm(); | |
| } else EIGEN_IF_CONSTEXPR (Mode == 1) { | |
| return Eigen::numext::sqrt((position - target.head(size)).array().square().sum()); | |
| } else { | |
| return (position.array() - target.head(size).array()).matrix().norm(); | |
| } | |
| } | |
| template <int Mode> | |
| Eigen::VectorXd bounded_residuals(const Eigen::MatrixXd& points, Eigen::Index size) { | |
| Eigen::VectorXd result(points.cols()); | |
| for (Eigen::Index i = 0; i < points.cols(); ++i) | |
| result(i) = bounded_residual<Mode>(BoundedVector3d(points.col(i)), size); | |
| return result; | |
| } | |
| int main() { | |
| evaluate_position = [](Eigen::Index size) -> Eigen::VectorXd { return Eigen::VectorXd::Zero(size); }; | |
| for (Eigen::Index size = 1; size <= 3; ++size) { | |
| const Eigen::MatrixXd points = Eigen::MatrixXd::Ones(size, 2); | |
| for (const Eigen::VectorXd& result : | |
| {bounded_residuals<0>(points, size), bounded_residuals<1>(points, size), bounded_residuals<2>(points, size)}) { | |
| for (Eigen::Index i = 0; i < result.size(); ++i) | |
| if (Eigen::numext::abs(result(i) - Eigen::numext::sqrt(double(size))) > 1e-12) return 1; | |
| } | |
| } | |
| } |