blob: 81f9b113a29dfb02a69a17288a0f83ba0a2d9e35 [file] [edit]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
// Exercise the shared kernel even when an ISA-specific TRSM implementation is available.
#define EIGEN_USE_AVX512_TRSM_KERNELS 0
// Keep the cancelling terms in one diagonal panel; synthetic kc=1 moves them into separate GEMM updates.
#define EIGEN_NO_DEBUG_SMALL_PRODUCT_BLOCKS
#include "main.h"
#include <Eigen/Core>
template <typename Scalar>
void trsm_packet_cancellation() {
STATIC_CHECK((internal::triangular_solve_packet_traits<Scalar>::UseUnblocked ==
internal::triangular_solve_packet_traits<Scalar>::Enabled));
using Triangle = Matrix<Scalar, Dynamic, Dynamic, RowMajor>;
using Operand = Matrix<Scalar, Dynamic, Dynamic, ColMajor>;
std::ptrdiff_t saved_l1, saved_l2, saved_l3, saved_l3_per_cpu;
internal::manage_caching_sizes(GetAction, &saved_l1, &saved_l2, &saved_l3, &saved_l3_per_cpu);
// Deterministic panels for the blocked cases, including AVX-512 double precision.
setCpuCacheSizes(64 * 1024, 2 * 1024 * 1024, 16 * 1024 * 1024);
const Index packet = internal::packet_traits<Scalar>::size;
const Scalar half_max = (std::numeric_limits<Scalar>::max)() / Scalar(2);
const Scalar large = ((std::numeric_limits<Scalar>::max)() / Scalar(4)) * Scalar(3);
for (Index n : {4, 8, 16, 128, 256}) {
for (Index offset : {Index(0), n - 4}) {
Triangle a = Triangle::Identity(n, n);
a(offset + 3, offset) = -half_max;
a(offset + 3, offset + 1) = half_max;
a.template triangularView<StrictlyUpper>().setConstant(NumTraits<Scalar>::quiet_NaN());
const Index widths[] = {packet, 2 * packet, 2 * packet + 1, 4 * packet + 3};
for (Index nrhs : widths) {
Operand b = Operand::Ones(n, nrhs), x(n, nrhs);
b.row(offset + 3).setConstant(large);
// Only alternating columns overflow, exercising mixed packet lanes and scalar tails.
for (Index j = 1; j < nrhs; j += 2) b(offset + 3, j) = Scalar(1);
x = b;
a.template triangularView<Lower>().solveInPlace(x);
VERIFY(x.array().isFinite().all());
// Four eps covers reciprocal/multiply rounding, including fast-math reciprocals.
VERIFY(((x - b).cwiseAbs().array() <= Scalar(4) * NumTraits<Scalar>::epsilon() * b.array()).all());
Triangle upper = a.reverse();
const Operand reversed = b.colwise().reverse();
x = reversed;
upper.template triangularView<Upper>().solveInPlace(x);
VERIFY(x.array().isFinite().all());
VERIFY(
((x - reversed).cwiseAbs().array() <= Scalar(4) * NumTraits<Scalar>::epsilon() * reversed.array()).all());
a.diagonal().setConstant(NumTraits<Scalar>::quiet_NaN());
upper.diagonal().setConstant(NumTraits<Scalar>::quiet_NaN());
x = b;
a.template triangularView<UnitLower>().solveInPlace(x);
VERIFY(x.array().isFinite().all());
VERIFY_IS_CWISE_EQUAL(x, b);
x = reversed;
upper.template triangularView<UnitUpper>().solveInPlace(x);
VERIFY(x.array().isFinite().all());
VERIFY_IS_CWISE_EQUAL(x, reversed);
Matrix<Scalar, Dynamic, Dynamic, RowMajor> right = b.transpose();
a.transpose().template triangularView<UnitUpper>().template solveInPlace<OnTheRight>(right);
VERIFY(right.array().isFinite().all());
VERIFY_IS_CWISE_EQUAL(right, b.transpose());
a.diagonal().setOnes();
}
}
}
internal::manage_caching_sizes(SetAction, &saved_l1, &saved_l2, &saved_l3, &saved_l3_per_cpu);
}
EIGEN_DECLARE_TEST(trsm_packet_cancellation) {
for (int i = 0; i < g_repeat; ++i) {
CALL_SUBTEST_1(trsm_packet_cancellation<float>());
CALL_SUBTEST_2(trsm_packet_cancellation<double>());
}
}