Core: Fix the blocked triangular solve for a right-hand side with a runtime inner stride libeigen/eigen!2985 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
diff --git a/Eigen/src/Core/products/TriangularSolverMatrix.h b/Eigen/src/Core/products/TriangularSolverMatrix.h index 946fd5d..f720f73 100644 --- a/Eigen/src/Core/products/TriangularSolverMatrix.h +++ b/Eigen/src/Core/products/TriangularSolverMatrix.h
@@ -282,7 +282,7 @@ #endif trsmKernelL<Scalar, Index, Mode, Conjugate, TriStorageOrder, OtherInnerStride, /*Specialized=*/true>::kernel( actualPanelWidth, actual_cols, _tri + i + (i)*triStride, triStride, - _other + i * OtherInnerStride + j2 * otherStride, otherIncr, otherStride); + _other + i * otherIncr + j2 * otherStride, otherIncr, otherStride); } Index lengthTarget = actual_kc - k1 - actualPanelWidth; @@ -434,8 +434,8 @@ trsmKernelR<Scalar, Index, Mode, Conjugate, TriStorageOrder, OtherInnerStride, /*Specialized=*/true>::kernel(actualPanelWidth, actual_mc, _tri + absolute_j2 + absolute_j2 * triStride, triStride, - _other + i2 * OtherInnerStride + absolute_j2 * otherStride, - otherIncr, otherStride); + _other + i2 * otherIncr + absolute_j2 * otherStride, otherIncr, + otherStride); } // pack the just computed part of lhs to A pack_lhs_panel(blockA, lhs.getSubMapper(i2, absolute_j2), actualPanelWidth, actual_mc, actual_kc, j2);
diff --git a/test/product_trsolve.cpp b/test/product_trsolve.cpp index cab1f0b..7f95e7f 100644 --- a/test/product_trsolve.cpp +++ b/test/product_trsolve.cpp
@@ -98,6 +98,21 @@ VERIFY_TRSM(cmLhs.conjugate().template triangularView<Lower>(), map1); buffer.setZero(); VERIFY_TRSM(cmLhs.template triangularView<Lower>(), map2); + + // A runtime inner stride reaches the blocked kernels as OtherInnerStride == Dynamic, which the + // compile-time 2 above does not; their panel offsets once multiplied by that constant. + Map<Matrix<Scalar, Size, Cols, colmajor>, 0, Stride<Dynamic, Dynamic> > map3( + buffer.data(), cmRhs.rows(), cmRhs.cols(), Stride<Dynamic, Dynamic>(2 * cmRhs.outerStride(), 2)); + Map<Matrix<Scalar, Size, Cols, rowmajor>, 0, Stride<Dynamic, Dynamic> > map4( + buffer.data(), rmRhs.rows(), rmRhs.cols(), Stride<Dynamic, Dynamic>(2 * rmRhs.outerStride(), 2)); + buffer.setZero(); + VERIFY_TRSM(cmLhs.template triangularView<Lower>(), map3); + buffer.setZero(); + VERIFY_TRSM(cmLhs.template triangularView<Upper>(), map4); + buffer.setZero(); + VERIFY_TRSM_ONTHERIGHT(cmLhs.template triangularView<Lower>(), map3); + buffer.setZero(); + VERIFY_TRSM_ONTHERIGHT(cmLhs.template triangularView<Upper>(), map4); } if (Size == Dynamic) { @@ -157,6 +172,24 @@ VERIFY_IS_APPROX(lhs.triangularView<Upper>().toDenseMatrix() * MatrixX(map), ref); } + // Runtime inner stride (OtherInnerStride == Dynamic), both sides + { + int cols = 5; + MatrixX buffer(2 * n, 2 * cols); + Map<MatrixX, 0, Stride<Dynamic, Dynamic> > map(buffer.data(), n, cols, Stride<Dynamic, Dynamic>(2 * n, 2)); + MatrixX ref(n, cols); + buffer.setZero(); + map.setRandom(); + ref = map; + lhs.triangularView<Lower>().solveInPlace(map); + VERIFY_IS_APPROX(lhs.triangularView<Lower>().toDenseMatrix() * MatrixX(map), ref); + buffer.setZero(); + map.setRandom(); + ref = map; + lhs.triangularView<Upper>().template solveInPlace<OnTheRight>(map.transpose()); + VERIFY_IS_APPROX(MatrixX(map.transpose()) * lhs.triangularView<Upper>().toDenseMatrix(), ref.transpose()); + } + // InnerStride = 2: UnitLower (tests the UnitDiag path without diagonal scaling) { int cols = 3;