Add test coverage for strided maps, triangular blocking, and mixed storage orders

libeigen/eigen!2288

Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
This commit is contained in:
Rasmus Munk Larsen
2026-03-12 14:07:21 -07:00
parent 93aa959b8a
commit 15cae83485
3 changed files with 202 additions and 2 deletions

View File

@@ -109,6 +109,56 @@ void real_complex(DenseIndex rows = MatrixType::RowsAtCompileTime, DenseIndex co
VERIFY(g_called && "matrix<complex> - real not properly optimized");
}
// Test linear structure operations between matrices with different storage orders.
// When storage orders differ, vectorization is disabled (StorageOrdersAgree=false in
// AssignEvaluator.h), exercising the scalar fallback path.
template <typename Scalar>
void linearStructure_mixed_storage() {
const Index PS = internal::packet_traits<Scalar>::size;
// Sizes at vectorization boundaries to expose any mismatch in traversal
const Index sizes[] = {1, PS, PS + 1, 2 * PS, 2 * PS + 1, 4 * PS + 1, 16};
typedef Matrix<Scalar, Dynamic, Dynamic, ColMajor> ColMat;
typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMat;
for (int si = 0; si < 7; ++si) {
Index n = sizes[si];
if (n <= 0) continue;
ColMat mc = ColMat::Random(n, n);
RowMat mr = RowMat::Random(n, n);
// ColMajor + RowMajor → ColMajor
ColMat sum_c = mc + mr;
for (Index j = 0; j < n; ++j)
for (Index i = 0; i < n; ++i) VERIFY_IS_APPROX(sum_c(i, j), mc(i, j) + mr(i, j));
// ColMajor - RowMajor → ColMajor
ColMat diff_c = mc - mr;
for (Index j = 0; j < n; ++j)
for (Index i = 0; i < n; ++i) VERIFY_IS_APPROX(diff_c(i, j), mc(i, j) - mr(i, j));
// RowMajor + ColMajor → RowMajor
RowMat sum_r = mr + mc;
for (Index j = 0; j < n; ++j)
for (Index i = 0; i < n; ++i) VERIFY_IS_APPROX(sum_r(i, j), mr(i, j) + mc(i, j));
// Assignment between storage orders
ColMat from_row = mr;
VERIFY_IS_APPROX(from_row, mr);
RowMat from_col = mc;
VERIFY_IS_APPROX(from_col, mc);
// cwiseProduct with mixed storage
ColMat cwp = mc.cwiseProduct(mr);
for (Index j = 0; j < n; ++j)
for (Index i = 0; i < n; ++i) VERIFY_IS_APPROX(cwp(i, j), mc(i, j) * mr(i, j));
// += with mixed storage
ColMat mc2 = mc;
mc2 += mr;
VERIFY_IS_APPROX(mc2, sum_c);
}
}
template <int>
void linearstructure_overflow() {
// make sure that /=scalar and /scalar do not overflow
@@ -147,4 +197,9 @@ EIGEN_DECLARE_TEST(linearstructure) {
CALL_SUBTEST_11(real_complex<ArrayXXcf>(10, 10));
}
CALL_SUBTEST_4(linearstructure_overflow<0>());
// Mixed storage order tests (deterministic, outside g_repeat).
CALL_SUBTEST_12(linearStructure_mixed_storage<float>());
CALL_SUBTEST_12(linearStructure_mixed_storage<double>());
CALL_SUBTEST_12(linearStructure_mixed_storage<std::complex<float>>());
}