blob: a2fc94723c07f90c29ea0857c310bbe8702b00b4 [file]
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0
#include <benchmark/benchmark.h>
#include <Eigen/Core>
#include <cmath>
#include <complex>
#include <limits>
using namespace Eigen;
// Scalar helpers also serve strided expressions and the tails of vectorized expressions.
template <typename T, bool Reciprocal>
static void BM_ComplexRoot(benchmark::State& state) {
using C = std::complex<T>;
const Index size = state.range(0);
const int mode = int(state.range(1));
Array<C, Dynamic, 1> input(size), output(size), reference(size);
for (Index i = 0; i < size; ++i) {
int exponent = int(i % 9) - 4;
if (mode == 1) exponent = std::numeric_limits<T>::max_exponent - 4 + int(i % 2);
if (mode == 2) exponent = std::numeric_limits<T>::min_exponent - std::numeric_limits<T>::digits + int(i % 9);
const T scale = std::ldexp(T(1), exponent);
const T root_scale = std::sqrt(scale);
const T x_sign = i % 2 ? T(-1) : T(1);
const T y_sign = i % 3 ? T(-1) : T(1);
const T u = x_sign > 0 ? T(2) : T(1);
const T v = x_sign > 0 ? T(1) : T(2);
input(i) = C(x_sign * T(3) * scale, y_sign * T(4) * scale);
reference(i) = Reciprocal ? C((u / T(5)) / root_scale, (-y_sign * v / T(5)) / root_scale)
: C(u * root_scale, y_sign * v * root_scale);
}
const auto operation = [](const C& z) { return Reciprocal ? numext::rsqrt(z) : numext::sqrt(z); };
output = input.unaryExpr(operation);
for (Index i = 0; i < size; ++i) {
const C error = output(i) / reference(i) - C(T(1));
if (!(std::abs(error) <= T(8) * NumTraits<T>::epsilon())) {
state.SkipWithError("complex root failed reference validation");
return;
}
}
for (auto _ : state) {
benchmark::DoNotOptimize(input.data());
output = input.unaryExpr(operation);
benchmark::DoNotOptimize(output.data());
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations() * size);
state.SetLabel(mode == 0 ? "ordinary" : mode == 1 ? "large" : "subnormal");
}
BENCHMARK_TEMPLATE(BM_ComplexRoot, float, false)->ArgsProduct({{1, 16, 4097}, {0, 1, 2}});
BENCHMARK_TEMPLATE(BM_ComplexRoot, double, false)->ArgsProduct({{1, 16, 4097}, {0, 1, 2}});
BENCHMARK_TEMPLATE(BM_ComplexRoot, float, true)->ArgsProduct({{1, 16, 4097}, {0, 1, 2}});
BENCHMARK_TEMPLATE(BM_ComplexRoot, double, true)->ArgsProduct({{1, 16, 4097}, {0, 1, 2}});