| // SPDX-FileCopyrightText: The Eigen Authors | |
| // SPDX-License-Identifier: MPL-2.0 | |
| #include <benchmark/benchmark.h> | |
| #include <Eigen/Core> | |
| #include <contrib/Eigen/StructuredMatrices> | |
| using Eigen::Circulant; | |
| using Eigen::Dynamic; | |
| using Eigen::Index; | |
| using Eigen::Matrix; | |
| template <typename Scalar> | |
| static void BM_CirculantSolveReciprocals(benchmark::State& state) { | |
| using Mat = Matrix<Scalar, Dynamic, Dynamic>; | |
| using RealScalar = typename Eigen::NumTraits<Scalar>::Real; | |
| const Index n = state.range(0), nrhs = state.range(1), kind = state.range(2); | |
| Matrix<Scalar, Dynamic, 1> generator = Matrix<Scalar, Dynamic, 1>::Zero(n); | |
| if (kind == 0) { | |
| for (Index k = 0; k < n; ++k) generator(k) = Scalar(RealScalar(k % 17 - 8) / RealScalar(16)); | |
| generator(0, 0) += Scalar(2 * n); | |
| } else if (kind == 1) { | |
| generator(0, 0) = Scalar(1); // Real symbol: exercises the scalar fallback. | |
| } else { | |
| generator.setConstant(Scalar(1)); // Only the DC mode survives the threshold. | |
| } | |
| const Circulant<Scalar> op(generator); | |
| Mat expected(n, nrhs); | |
| for (Index k = 0; k < expected.size(); ++k) | |
| expected(k) = kind == 2 ? Scalar(1) : Scalar(RealScalar(k % 13 - 6) / RealScalar(8)); | |
| const Mat rhs = op * expected; | |
| Mat solution = op.solve(rhs); | |
| // The round trip through these well-conditioned operators costs O(log N) eps. | |
| if (!solution.allFinite() || | |
| (solution - expected).norm() > RealScalar(128) * Eigen::NumTraits<RealScalar>::epsilon() * expected.norm()) { | |
| state.SkipWithError("Circulant solve round-trip check failed"); | |
| return; | |
| } | |
| for (auto _ : state) { | |
| solution = op.solve(rhs); | |
| benchmark::DoNotOptimize(solution.data()); | |
| benchmark::ClobberMemory(); | |
| } | |
| } | |
| BENCHMARK_TEMPLATE(BM_CirculantSolveReciprocals, float)->ArgsProduct({{15, 64, 1024, 16384}, {1, 8}, {0, 1, 2}}); | |
| BENCHMARK_TEMPLATE(BM_CirculantSolveReciprocals, double)->ArgsProduct({{15, 64, 1024, 16384}, {1, 8}, {0, 1, 2}}); | |
| BENCHMARK_TEMPLATE(BM_CirculantSolveReciprocals, std::complex<float>) | |
| ->ArgsProduct({{15, 64, 1024, 16384}, {1, 8}, {0, 1, 2}}); | |
| BENCHMARK_TEMPLATE(BM_CirculantSolveReciprocals, std::complex<double>) | |
| ->ArgsProduct({{15, 64, 1024, 16384}, {1, 8}, {0, 1, 2}}); |