diff --git a/Eigen/src/Core/products/GeneralMatrixVector.h b/Eigen/src/Core/products/GeneralMatrixVector.h index e0205defb..40694f2e6 100644 --- a/Eigen/src/Core/products/GeneralMatrixVector.h +++ b/Eigen/src/Core/products/GeneralMatrixVector.h @@ -652,17 +652,20 @@ general_matrix_vector_product(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 diff --git a/test/product_large.cpp b/test/product_large.cpp index 4b8e52d5d..79d77abd2 100644 --- a/test/product_large.cpp +++ b/test/product_large.cpp @@ -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 +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 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 void bug_1622() { typedef Matrix 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