blob: 0f33d00b9069131b0934942dae1cdd519e009e52 [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;
// The packet path, plog_complex, for whole packets. Inputs (+-3, +-4) * 2^e with ordinary, large and subnormal e;
// log|z| = log(5) + e log(2) and arg z = atan2(+-4, +-3).
template <typename T>
static void BM_ComplexLogPacket(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);
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);
input(i) = C((i % 2 ? T(-3) : T(3)) * scale, (i % 3 ? T(-4) : T(4)) * scale);
}
output = input.log();
for (Index i = 0; i < size; ++i) {
const T x = std::real(input(i)) / std::ldexp(T(1), std::ilogb(std::real(input(i))) - 1);
const T y = std::imag(input(i)) / std::ldexp(T(1), std::ilogb(std::real(input(i))) - 1);
const T log_abs = std::log(T(5)) + T(std::ilogb(std::real(input(i))) - 1) * std::log(T(2));
const T tol = T(16) * NumTraits<T>::epsilon();
if (!(std::abs(std::real(output(i)) - log_abs) <= tol * std::abs(log_abs)) ||
!(std::abs(std::imag(output(i)) - std::atan2(y, x)) <= tol)) {
state.SkipWithError("complex log failed reference validation");
return;
}
}
for (auto _ : state) {
benchmark::DoNotOptimize(input.data());
output = input.log();
benchmark::DoNotOptimize(output.data());
benchmark::ClobberMemory();
}
state.SetItemsProcessed(state.iterations() * size);
state.SetLabel(mode == 0 ? "ordinary" : mode == 1 ? "large" : "subnormal");
}
BENCHMARK_TEMPLATE(BM_ComplexLogPacket, float)->ArgsProduct({{16, 4096}, {0, 1, 2}});
BENCHMARK_TEMPLATE(BM_ComplexLogPacket, double)->ArgsProduct({{16, 4096}, {0, 1, 2}});