blob: e071dc6fc6ed74a15d33fdb23fb64e3d087ff074 [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/Core>
using namespace Eigen;
template <int Operation, typename Mat, typename Vec>
static void selfadjoint_diagonal(Mat& dst, const Mat& matrix, const Vec& diagonal) {
if (Operation == 0) dst.noalias() = matrix.template selfadjointView<Lower>() * diagonal.asDiagonal();
if (Operation == 1)
dst = (matrix.template selfadjointView<Lower>() * diagonal.asDiagonal()) + Mat::Zero(dst.rows(), dst.cols());
if (Operation == 2)
dst = ((typename Mat::Scalar(2) * matrix.template selfadjointView<Lower>()) * diagonal.asDiagonal()) +
Mat::Zero(dst.rows(), dst.cols());
}
template <typename Scalar, int Order, int Operation>
static void BM_SelfAdjointDiagonal(benchmark::State& state) {
using Mat = Matrix<Scalar, Dynamic, Dynamic, Order>;
using Vec = Matrix<Scalar, Dynamic, 1>;
using Real = typename NumTraits<Scalar>::Real;
const Index n = state.range(0);
Mat matrix = Mat::Random(n, n), dst(n, n);
const Vec diagonal = Vec::Random(n);
matrix.diagonal() = matrix.diagonal().real().template cast<Scalar>();
selfadjoint_diagonal<Operation>(dst, matrix, diagonal);
for (Index j = 0; j < n; ++j) {
for (Index i = 0; i < n; ++i) {
Scalar value = (i >= j ? matrix(i, j) : numext::conj(matrix(j, i))) * diagonal(j);
if (Operation == 2) value *= Scalar(2);
const Real bound = Real(16) * NumTraits<Real>::epsilon() * (Real(1) + numext::abs(value));
if (!(numext::abs(dst(i, j) - value) <= bound)) {
state.SkipWithError("Selfadjoint/diagonal product disagrees with the scalar reference");
return;
}
}
}
for (auto _ : state) {
selfadjoint_diagonal<Operation>(dst, matrix, diagonal);
benchmark::DoNotOptimize(dst.data());
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations() * n * n);
}
#define SELFADJOINT_DIAGONAL_SIZES ->Arg(3)->Arg(16)->Arg(33)->Arg(65)->Arg(128)->Arg(512)
#define SELFADJOINT_DIAGONAL_OPERATIONS(SCALAR, ORDER) \
BENCHMARK_TEMPLATE(BM_SelfAdjointDiagonal, SCALAR, ORDER, 0) SELFADJOINT_DIAGONAL_SIZES; \
BENCHMARK_TEMPLATE(BM_SelfAdjointDiagonal, SCALAR, ORDER, 1) SELFADJOINT_DIAGONAL_SIZES; \
BENCHMARK_TEMPLATE(BM_SelfAdjointDiagonal, SCALAR, ORDER, 2) SELFADJOINT_DIAGONAL_SIZES
SELFADJOINT_DIAGONAL_OPERATIONS(double, ColMajor);
SELFADJOINT_DIAGONAL_OPERATIONS(double, RowMajor);
SELFADJOINT_DIAGONAL_OPERATIONS(std::complex<double>, ColMajor);
SELFADJOINT_DIAGONAL_OPERATIONS(std::complex<double>, RowMajor);
#undef SELFADJOINT_DIAGONAL_OPERATIONS
#undef SELFADJOINT_DIAGONAL_SIZES