mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
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:
@@ -167,12 +167,83 @@ void check_const_correctness(const PlainObjectType&) {
|
||||
|
||||
// verify that map-to-const don't have LvalueBit
|
||||
typedef std::add_const_t<PlainObjectType> ConstPlainObjectType;
|
||||
VERIFY(!(internal::traits<Map<ConstPlainObjectType> >::Flags & LvalueBit));
|
||||
VERIFY(!(internal::traits<Map<ConstPlainObjectType, AlignedMax> >::Flags & LvalueBit));
|
||||
VERIFY(!(internal::traits<Map<ConstPlainObjectType>>::Flags & LvalueBit));
|
||||
VERIFY(!(internal::traits<Map<ConstPlainObjectType, AlignedMax>>::Flags & LvalueBit));
|
||||
VERIFY(!(Map<ConstPlainObjectType>::Flags & LvalueBit));
|
||||
VERIFY(!(Map<ConstPlainObjectType, AlignedMax>::Flags & LvalueBit));
|
||||
}
|
||||
|
||||
// Test Map with InnerStride at vectorization boundary sizes.
|
||||
// Strided Maps exercise different traversal paths (SliceVectorized or Default)
|
||||
// in assignment and reductions.
|
||||
template <typename Scalar>
|
||||
void map_inner_stride_boundary() {
|
||||
const Index PS = internal::packet_traits<Scalar>::size;
|
||||
const Index sizes[] = {1, 2, 3, PS - 1, PS, PS + 1, 2 * PS, 2 * PS + 1, 4 * PS, 4 * PS + 1};
|
||||
for (int si = 0; si < 10; ++si) {
|
||||
const Index n = sizes[si];
|
||||
if (n <= 0) continue;
|
||||
typedef Matrix<Scalar, Dynamic, 1> Vec;
|
||||
// InnerStride<2>: every other element
|
||||
Vec data = Vec::Random(2 * n);
|
||||
Map<Vec, 0, InnerStride<2>> strided(data.data(), n);
|
||||
|
||||
// Test assignment to/from strided map
|
||||
Vec dense = strided;
|
||||
for (Index k = 0; k < n; ++k) VERIFY_IS_APPROX(dense(k), data(2 * k));
|
||||
|
||||
// Test scalar operations on strided map
|
||||
Vec result = Scalar(2) * strided;
|
||||
for (Index k = 0; k < n; ++k) VERIFY_IS_APPROX(result(k), Scalar(2) * data(2 * k));
|
||||
|
||||
// Test strided map + dense vector
|
||||
Vec other = Vec::Random(n);
|
||||
Vec sum_result = strided + other;
|
||||
for (Index k = 0; k < n; ++k) VERIFY_IS_APPROX(sum_result(k), data(2 * k) + other(k));
|
||||
|
||||
// Test writing to strided map
|
||||
Map<Vec, 0, InnerStride<2>> strided_dst(data.data(), n);
|
||||
strided_dst = other;
|
||||
for (Index k = 0; k < n; ++k) VERIFY_IS_APPROX(data(2 * k), other(k));
|
||||
}
|
||||
}
|
||||
|
||||
// Test Map with OuterStride on matrices at boundary sizes.
|
||||
template <typename Scalar>
|
||||
void map_outer_stride_boundary() {
|
||||
const Index PS = internal::packet_traits<Scalar>::size;
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic> Mat;
|
||||
// Test various inner dimensions around packet size
|
||||
const Index inner_sizes[] = {1, PS - 1, PS, PS + 1, 2 * PS, 2 * PS + 1};
|
||||
const Index outer_stride = 64; // large enough for any inner size
|
||||
const Index cols = 4;
|
||||
|
||||
for (int si = 0; si < 6; ++si) {
|
||||
Index rows = inner_sizes[si];
|
||||
if (rows <= 0) continue;
|
||||
typedef Matrix<Scalar, Dynamic, 1> Vec;
|
||||
Vec data = Vec::Random(outer_stride * cols);
|
||||
Map<Mat, 0, OuterStride<>> mapped(data.data(), rows, cols, OuterStride<>(outer_stride));
|
||||
|
||||
// Test that mapped values match expected layout
|
||||
Mat dense = mapped;
|
||||
for (Index j = 0; j < cols; ++j)
|
||||
for (Index i = 0; i < rows; ++i) VERIFY_IS_APPROX(dense(i, j), data(j * outer_stride + i));
|
||||
|
||||
// Test reduction on mapped matrix
|
||||
Scalar ref_sum(0);
|
||||
for (Index j = 0; j < cols; ++j)
|
||||
for (Index i = 0; i < rows; ++i) ref_sum += data(j * outer_stride + i);
|
||||
VERIFY_IS_APPROX(mapped.sum(), ref_sum);
|
||||
|
||||
// Test matrix product with mapped matrix
|
||||
Vec x = Vec::Random(cols);
|
||||
Vec y = mapped * x;
|
||||
Vec y_ref = dense * x;
|
||||
VERIFY_IS_APPROX(y, y_ref);
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(mapped_matrix) {
|
||||
for (int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(map_class_vector(Matrix<float, 1, 1>()));
|
||||
@@ -197,4 +268,10 @@ EIGEN_DECLARE_TEST(mapped_matrix) {
|
||||
CALL_SUBTEST_9(map_static_methods(VectorXcd(8)));
|
||||
CALL_SUBTEST_10(map_static_methods(VectorXf(12)));
|
||||
}
|
||||
|
||||
// Strided map tests at vectorization boundaries (deterministic, outside g_repeat).
|
||||
CALL_SUBTEST_12(map_inner_stride_boundary<float>());
|
||||
CALL_SUBTEST_12(map_inner_stride_boundary<double>());
|
||||
CALL_SUBTEST_13(map_outer_stride_boundary<float>());
|
||||
CALL_SUBTEST_13(map_outer_stride_boundary<double>());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user