blob: 292d42c5bbd40ccc386942b9534d0a19af8efec0 [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/Core>
#include <algorithm>
#include <cstdlib>
#include <random>
namespace {
using namespace Eigen;
template <bool InPlace, unsigned int UpLo, typename MatrixType, typename PermutationType>
void permute(MatrixType& matrix, const PermutationType& permutation, bool inverse) {
EIGEN_IF_CONSTEXPR (InPlace) {
if (inverse)
matrix.template selfadjointView<UpLo>().applyPermutation(permutation.inverse());
else
matrix.template selfadjointView<UpLo>().applyPermutation(permutation);
} else {
if (inverse)
matrix.template selfadjointView<UpLo>() =
(permutation.inverse() * matrix.template selfadjointView<UpLo>() * permutation).eval();
else
matrix.template selfadjointView<UpLo>() =
(permutation * matrix.template selfadjointView<UpLo>() * permutation.transpose()).eval();
}
}
template <typename Scalar, int Order, unsigned int UpLo, bool InPlace>
void BM_SelfAdjointPermutation(benchmark::State& state) {
using MatrixType = Matrix<Scalar, Dynamic, Dynamic, Order>;
const Index size = state.range(0);
std::srand(42);
MatrixType matrix = MatrixType::Random(size, size);
matrix.diagonal() = matrix.diagonal().real().template cast<Scalar>();
PermutationMatrix<Dynamic> permutation(size);
permutation.setIdentity();
std::mt19937 random(42);
if (state.range(1) == 0) {
std::shuffle(permutation.indices().data(), permutation.indices().data() + size, random);
} else {
permutation.indices().reverseInPlace();
}
const MatrixType full = matrix.template selfadjointView<UpLo>();
const bool inverse = state.range(2) != 0;
MatrixType reference(size, size);
if (inverse)
reference = permutation.inverse() * full * permutation;
else
reference = permutation * full * permutation.transpose();
MatrixType expected = matrix;
expected.template triangularView<UpLo>() = reference;
permute<InPlace, UpLo>(matrix, permutation, inverse);
if (matrix != expected) {
state.SkipWithError("Incorrect self-adjoint permutation or modified opposite triangle");
return;
}
for (auto _ : state) {
permute<InPlace, UpLo>(matrix, permutation, inverse);
benchmark::DoNotOptimize(matrix.data());
benchmark::ClobberMemory();
}
}
// Permutation kind: 0 = shuffled (seed 42), 1 = reversal. Last argument selects the inverse.
#define EIGEN_BENCH_SELFADJOINT_PERMUTATION(Scalar, Order, UpLo) \
BENCHMARK_TEMPLATE(BM_SelfAdjointPermutation, Scalar, Order, UpLo, false) \
->ArgsProduct({{4, 16, 64, 256, 1024}, {0, 1}, {0, 1}}); \
BENCHMARK_TEMPLATE(BM_SelfAdjointPermutation, Scalar, Order, UpLo, true) \
->ArgsProduct({{4, 16, 64, 256, 1024}, {0, 1}, {0, 1}})
EIGEN_BENCH_SELFADJOINT_PERMUTATION(float, ColMajor, Lower);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(float, RowMajor, Upper);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(double, ColMajor, Lower);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(double, RowMajor, Upper);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(std::complex<float>, ColMajor, Upper);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(std::complex<float>, RowMajor, Lower);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(std::complex<double>, ColMajor, Upper);
EIGEN_BENCH_SELFADJOINT_PERMUTATION(std::complex<double>, RowMajor, Lower);
#undef EIGEN_BENCH_SELFADJOINT_PERMUTATION
} // namespace