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