blob: 6e4f308714fc35c2500aa10ca881c0e326bafe00 [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/Eigenvalues>
#include <cstdlib>
#ifndef SCALAR
#define SCALAR double
#endif
// ExtraStride = -1 uses owning storage; 0 and 1 bind a Ref with leading dimension n and n+1.
template <int ExtraStride>
static void BM_RealSchur(benchmark::State& state) {
using Scalar = SCALAR;
using Mat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
using SolverMatrix = std::conditional_t<(ExtraStride < 0), Mat, Eigen::Ref<Mat>>;
const Eigen::Index n = state.range(0);
const bool vectors = state.range(1) != 0;
const bool fromHessenberg = state.range(2) == 1;
std::srand(5489);
Mat matrix = Mat::Random(n, n);
if (fromHessenberg) {
Eigen::HessenbergDecomposition<Mat> hess(matrix);
matrix = hess.matrixH();
} else if (state.range(2) == 2) {
matrix.template triangularView<Eigen::StrictlyLower>().setZero();
}
const Mat identity = Mat::Identity(n, n);
Mat storage(n + (ExtraStride > 0 ? ExtraStride : 0), n);
auto workspace = storage.topRows(n);
workspace = identity;
Eigen::RealSchur<SolverMatrix> solver(workspace);
const auto compute = [&](bool computeU) {
if (fromHessenberg)
solver.computeFromHessenberg(matrix, identity, computeU);
else
solver.compute(matrix, computeU);
};
compute(true);
const Scalar bound = Scalar(64 * n) * Eigen::NumTraits<Scalar>::epsilon();
if (solver.info() != Eigen::Success ||
!((matrix - solver.matrixU() * solver.matrixT() * solver.matrixU().transpose()).norm() <=
bound * matrix.norm()) ||
!((solver.matrixU().transpose() * solver.matrixU() - identity).norm() <= bound)) {
state.SkipWithError("RealSchur failed reconstruction or orthogonality check");
return;
}
const Mat referenceT = solver.matrixT();
compute(vectors);
if (solver.info() != Eigen::Success || !((solver.matrixT() - referenceT).norm() <= bound * matrix.norm())) {
state.SkipWithError("RealSchur failed values-only check");
return;
}
for (auto _ : state) {
compute(vectors);
benchmark::DoNotOptimize(solver.matrixT().data());
benchmark::ClobberMemory();
}
}
BENCHMARK_TEMPLATE(BM_RealSchur, -1)->ArgsProduct({{128, 129, 256, 257, 512, 1024}, {0, 1}, {0, 1, 2}})->UseRealTime();
BENCHMARK_TEMPLATE(BM_RealSchur, 0)->ArgsProduct({{128, 129, 256, 257, 512, 1024}, {0, 1}, {0, 1, 2}})->UseRealTime();
BENCHMARK_TEMPLATE(BM_RealSchur, 1)->ArgsProduct({{128, 129, 256, 257, 512, 1024}, {0, 1}, {0, 1, 2}})->UseRealTime();