Fix row-skipping bug in general_matrix_vector_product::run_small_cols

libeigen/eigen!2276
This commit is contained in:
Antonio Sánchez
2026-03-10 22:16:00 +00:00
committed by Rasmus Munk Larsen
parent 81550faea4
commit 4387e32481
2 changed files with 30 additions and 4 deletions

View File

@@ -652,17 +652,20 @@ general_matrix_vector_product<Index, LhsScalar, LhsMapper, RowMajor, ConjugateLh
const Index n2 = rows - 1;
Index i = 0;
for (; i < n8; i += 8)
for (; i < n8; i += 8) {
process_rows_small_cols<8>(i, cols, lhs, rhs, res, resIncr, alpha, halfColBlockEnd, quarterColBlockEnd);
if (i < n4) {
}
// Process remaining groups of 4 rows in case n8 was 0.
for (; i < n4; i += 4) {
process_rows_small_cols<4>(i, cols, lhs, rhs, res, resIncr, alpha, halfColBlockEnd, quarterColBlockEnd);
i += 4;
}
if (i < n2) {
process_rows_small_cols<2>(i, cols, lhs, rhs, res, resIncr, alpha, halfColBlockEnd, quarterColBlockEnd);
i += 2;
}
if (i < rows) process_rows_small_cols<1>(i, cols, lhs, rhs, res, resIncr, alpha, halfColBlockEnd, quarterColBlockEnd);
if (i < rows) {
process_rows_small_cols<1>(i, cols, lhs, rhs, res, resIncr, alpha, halfColBlockEnd, quarterColBlockEnd);
}
}
} // end namespace internal

View File

@@ -130,6 +130,28 @@ void bug_gemv_rowmajor_large_stride() {
}
}
// Regression test for row-major GEMV run_small_cols bug.
// When cols is small (e.g., 2), and loop variables (like n8) are 0 due
// to row or stride limits, the remainder loops previously used `if` checks
// like `if (i < n4)`. This incorrectly skips rows if multiple remainder
// blocks are needed (e.g., 9 rows).
template <int>
void bug_gemv_run_small_cols() {
const int rows = 9; // > 8, covers 8-row loop step but tests remainder cleanup
const int cols = 2; // triggers run_small_cols (cols < PacketSize)
const int stride = 5000; // 5000 * sizeof(double) > 32000, forces n8 = 0
Matrix<double, Dynamic, Dynamic, RowMajor> A_full(rows, stride);
A_full.setRandom();
auto A = A_full.leftCols(cols);
VectorXd x = VectorXd::Random(cols);
VectorXd y = A * x;
VectorXd y_ref = A.eval() * x; // No stride.
VERIFY_IS_APPROX(y, y_ref);
}
template <int>
void bug_1622() {
typedef Matrix<double, 2, -1, 0, 2, -1> Mat2X;
@@ -175,6 +197,7 @@ EIGEN_DECLARE_TEST(product_large) {
CALL_SUBTEST_6(product_large_regressions<0>());
CALL_SUBTEST_6(bug_gemv_rowmajor_large_stride<0>());
CALL_SUBTEST_6(bug_gemv_run_small_cols<0>());
// Regression test for bug 714:
#if defined EIGEN_HAS_OPENMP