mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Add test coverage for transpose, reverse, bool redux, select, diagonal-of-product at boundaries
libeigen/eigen!2290 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
This commit is contained in:
@@ -81,6 +81,79 @@ void diagonal_assert(const MatrixType& m) {
|
||||
VERIFY_RAISES_ASSERT(m1.diagonal(-(rows + 1)));
|
||||
}
|
||||
|
||||
// Test that (A * B).diagonal() gives the same result as (A * B).eval().diagonal().
|
||||
// The diagonal-of-product path uses LazyProduct evaluation (see ProductEvaluators.h),
|
||||
// which avoids computing the full product. Verify this optimization is correct.
|
||||
template <typename Scalar>
|
||||
void diagonal_of_product() {
|
||||
const Index PS = internal::packet_traits<Scalar>::size;
|
||||
const Index sizes[] = {1, 2, 3, PS - 1, PS, PS + 1, 2 * PS - 1, 2 * PS, 2 * PS + 1, 4 * PS, 4 * PS + 1};
|
||||
typedef Matrix<Scalar, Dynamic, Dynamic> Mat;
|
||||
typedef Matrix<Scalar, Dynamic, 1> Vec;
|
||||
|
||||
for (int si = 0; si < 11; ++si) {
|
||||
Index n = sizes[si];
|
||||
if (n <= 0) continue;
|
||||
|
||||
Mat A = Mat::Random(n, n);
|
||||
Mat B = Mat::Random(n, n);
|
||||
|
||||
// Lazy diagonal vs explicit product diagonal
|
||||
Vec diag_lazy = (A * B).diagonal();
|
||||
Vec diag_explicit = (A * B).eval().diagonal();
|
||||
VERIFY_IS_APPROX(diag_lazy, diag_explicit);
|
||||
|
||||
// Also test non-square: A is m×k, B is k×n
|
||||
for (int k : {1, 3, (int)n}) {
|
||||
if (k <= 0) continue;
|
||||
Mat C = Mat::Random(n, k);
|
||||
Mat D = Mat::Random(k, n);
|
||||
Vec diag_lazy2 = (C * D).diagonal();
|
||||
Vec diag_explicit2 = (C * D).eval().diagonal();
|
||||
VERIFY_IS_APPROX(diag_lazy2, diag_explicit2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test .select() at vectorization boundary sizes.
|
||||
// select() uses CwiseTernaryOp which has packet-level evaluation with remainder handling.
|
||||
template <typename Scalar>
|
||||
void select_boundary() {
|
||||
const Index PS = internal::packet_traits<Scalar>::size;
|
||||
const Index sizes[] = {1, 2, 3, PS - 1, PS, PS + 1, 2 * PS - 1, 2 * PS, 2 * PS + 1, 4 * PS, 4 * PS + 1};
|
||||
typedef Array<Scalar, Dynamic, 1> Arr;
|
||||
|
||||
for (int si = 0; si < 11; ++si) {
|
||||
Index n = sizes[si];
|
||||
if (n <= 0) continue;
|
||||
|
||||
Arr a = Arr::Random(n);
|
||||
Arr b = Arr::Random(n);
|
||||
auto cond = (a > Scalar(0));
|
||||
|
||||
// select with two arrays
|
||||
Arr result = cond.select(a, b);
|
||||
for (Index k = 0; k < n; ++k) {
|
||||
Scalar expected = (a(k) > Scalar(0)) ? a(k) : b(k);
|
||||
VERIFY_IS_APPROX(result(k), expected);
|
||||
}
|
||||
|
||||
// select with scalar else
|
||||
Arr result2 = cond.select(a, Scalar(0));
|
||||
for (Index k = 0; k < n; ++k) {
|
||||
Scalar expected = (a(k) > Scalar(0)) ? a(k) : Scalar(0);
|
||||
VERIFY_IS_APPROX(result2(k), expected);
|
||||
}
|
||||
|
||||
// select with scalar then
|
||||
Arr result3 = cond.select(Scalar(42), b);
|
||||
for (Index k = 0; k < n; ++k) {
|
||||
Scalar expected = (a(k) > Scalar(0)) ? Scalar(42) : b(k);
|
||||
VERIFY_IS_APPROX(result3(k), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EIGEN_DECLARE_TEST(diagonal) {
|
||||
for (int i = 0; i < g_repeat; i++) {
|
||||
CALL_SUBTEST_1(diagonal(Matrix<float, 1, 1>()));
|
||||
@@ -99,4 +172,14 @@ EIGEN_DECLARE_TEST(diagonal) {
|
||||
CALL_SUBTEST_1(diagonal_assert(
|
||||
MatrixXf(internal::random<int>(1, EIGEN_TEST_MAX_SIZE), internal::random<int>(1, EIGEN_TEST_MAX_SIZE))));
|
||||
}
|
||||
|
||||
// Diagonal-of-product optimization (deterministic, outside g_repeat).
|
||||
CALL_SUBTEST_3(diagonal_of_product<float>());
|
||||
CALL_SUBTEST_3(diagonal_of_product<double>());
|
||||
CALL_SUBTEST_3(diagonal_of_product<std::complex<float>>());
|
||||
|
||||
// Select at vectorization boundaries (deterministic, outside g_repeat).
|
||||
CALL_SUBTEST_4(select_boundary<float>());
|
||||
CALL_SUBTEST_4(select_boundary<double>());
|
||||
CALL_SUBTEST_4(select_boundary<int>());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user