Make permutation products aliasing by default.
diff --git a/Eigen/src/Core/PermutationMatrix.h b/Eigen/src/Core/PermutationMatrix.h index 4748b11..eb8e797 100644 --- a/Eigen/src/Core/PermutationMatrix.h +++ b/Eigen/src/Core/PermutationMatrix.h
@@ -468,17 +468,17 @@ /** \returns the matrix with the permutation applied to the columns. */ template <typename MatrixDerived, typename PermutationDerived> -EIGEN_DEVICE_FUNC const Product<MatrixDerived, PermutationDerived, AliasFreeProduct> operator*( +EIGEN_DEVICE_FUNC const Product<MatrixDerived, PermutationDerived, DefaultProduct> operator*( const MatrixBase<MatrixDerived>& matrix, const PermutationBase<PermutationDerived>& permutation) { - return Product<MatrixDerived, PermutationDerived, AliasFreeProduct>(matrix.derived(), permutation.derived()); + return Product<MatrixDerived, PermutationDerived, DefaultProduct>(matrix.derived(), permutation.derived()); } /** \returns the matrix with the permutation applied to the rows. */ template <typename PermutationDerived, typename MatrixDerived> -EIGEN_DEVICE_FUNC const Product<PermutationDerived, MatrixDerived, AliasFreeProduct> operator*( +EIGEN_DEVICE_FUNC const Product<PermutationDerived, MatrixDerived, DefaultProduct> operator*( const PermutationBase<PermutationDerived>& permutation, const MatrixBase<MatrixDerived>& matrix) { - return Product<PermutationDerived, MatrixDerived, AliasFreeProduct>(permutation.derived(), matrix.derived()); + return Product<PermutationDerived, MatrixDerived, DefaultProduct>(permutation.derived(), matrix.derived()); } template <typename PermutationType> @@ -520,16 +520,16 @@ /** \returns the matrix with the inverse permutation applied to the columns. */ template <typename OtherDerived> - friend const Product<OtherDerived, InverseType, AliasFreeProduct> operator*(const MatrixBase<OtherDerived>& matrix, - const InverseType& trPerm) { - return Product<OtherDerived, InverseType, AliasFreeProduct>(matrix.derived(), trPerm.derived()); + friend const Product<OtherDerived, InverseType, DefaultProduct> operator*(const MatrixBase<OtherDerived>& matrix, + const InverseType& trPerm) { + return Product<OtherDerived, InverseType, DefaultProduct>(matrix.derived(), trPerm.derived()); } /** \returns the matrix with the inverse permutation applied to the rows. */ template <typename OtherDerived> - const Product<InverseType, OtherDerived, AliasFreeProduct> operator*(const MatrixBase<OtherDerived>& matrix) const { - return Product<InverseType, OtherDerived, AliasFreeProduct>(derived(), matrix.derived()); + const Product<InverseType, OtherDerived, DefaultProduct> operator*(const MatrixBase<OtherDerived>& matrix) const { + return Product<InverseType, OtherDerived, DefaultProduct>(derived(), matrix.derived()); } };
diff --git a/test/permutationmatrices.cpp b/test/permutationmatrices.cpp index 2c83783..ee794b2 100644 --- a/test/permutationmatrices.cpp +++ b/test/permutationmatrices.cpp
@@ -39,7 +39,8 @@ RightTranspositionsType rt(rv); MatrixType m_permuted = MatrixType::Random(rows, cols); - VERIFY_EVALUATION_COUNT(m_permuted = lp * m_original * rp, 1); // 1 temp for sub expression "lp * m_original" + VERIFY_EVALUATION_COUNT(m_permuted.noalias() = lp * m_original * rp, + 1); // 1 temp for sub expression "lp * m_original" for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) VERIFY_IS_APPROX(m_permuted(lv(i), j), m_original(i, rv(j))); @@ -50,7 +51,7 @@ VERIFY_IS_APPROX(m_permuted, lm * m_original * rm); m_permuted = m_original; - VERIFY_EVALUATION_COUNT(m_permuted = lp * m_permuted * rp, 1); + VERIFY_EVALUATION_COUNT(m_permuted.noalias() = lp * m_permuted * rp, 1); VERIFY_IS_APPROX(m_permuted, lm * m_original * rm); LeftPermutationType lpi; @@ -169,6 +170,26 @@ VERIFY_IS_APPROX(v1, (P.inverse() * rhs).eval()); } +void test_aliasing() { + // Bug #2869. + auto P = Eigen::PermutationMatrix<4>{Eigen::Vector4i{0, 2, 3, 1}}; + { + Eigen::Vector<float, 5> z = {0.0f, 1.1f, 2.2f, 3.3f, 4.4f}; + Eigen::Vector<float, 5> expected = z; + z.tail<4>() = P * z.head<4>(); + expected.tail<4>() = (P * expected.head<4>()).eval(); + VERIFY_IS_APPROX(z, expected); + } + + { + // Obfuscate the aliasing in the RHS expression. + Eigen::Vector4f a = {1.1f, 2.2f, 3.3f, 4.4f}; + Eigen::Vector4f expected = P * (a + Eigen::Vector4f::Zero()).cwiseSqrt(); + a = P * (a + Eigen::Vector4f::Zero()).cwiseSqrt(); + VERIFY_IS_APPROX(a, expected); + } +} + EIGEN_DECLARE_TEST(permutationmatrices) { for (int i = 0; i < g_repeat; i++) { CALL_SUBTEST_1(permutationmatrices(Matrix<float, 1, 1>())); @@ -182,4 +203,5 @@ MatrixXcf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE)))); } CALL_SUBTEST_5(bug890<double>()); + CALL_SUBTEST_4(test_aliasing()); }