diff --git a/Benchmark/src/CMakeLists.txt b/Benchmark/src/CMakeLists.txt index e482eec..e576a4d 100644 --- a/Benchmark/src/CMakeLists.txt +++ b/Benchmark/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_benchmark(PWR003) add_benchmark(PWR022) add_benchmark(PWR032) +add_benchmark(PWR037) add_benchmark(PWR039) add_benchmark(PWR043) add_benchmark(PWR062) diff --git a/Benchmark/src/PWR037.cpp b/Benchmark/src/PWR037.cpp new file mode 100644 index 0000000..e4ac8a0 --- /dev/null +++ b/Benchmark/src/PWR037.cpp @@ -0,0 +1,54 @@ +#include "Benchmark.h" + +// Forward-declare the functions to benchmark +extern "C" { +void compute_damped_sinusoid(const int n, const double *timesteps, + const double amplitude, + const double angularFrequency, + const double decayRate, const double phaseShift, + double *results); +void compute_damped_sinusoid_improved(const int n, const double *timesteps, + const double amplitude, + const double angularFrequency, + const double decayRate, + const double phaseShift, double *results); +} + +// Size adjusted to fit execution on micro-seconds +constexpr int N = 1024 * 1024; +constexpr double AMPLITUDE = 1.0; +constexpr double ANGULAR_FREQUENCY = 2.0; +constexpr double DECAY_RATE = 0.5; +constexpr double PHASE_SHIFT = 3.141592653589793 / 4; + +#if OCB_ENABLE_C + +static void CExampleBench(benchmark::State &state) { + const auto timesteps = OpenCatalog::CreateRandomVector(N, 0.0, 10.0); + auto results = OpenCatalog::CreateUninitializedVector(N); + + for (auto _ : state) { + compute_damped_sinusoid(N, timesteps.data(), AMPLITUDE, ANGULAR_FREQUENCY, + DECAY_RATE, PHASE_SHIFT, results.data()); + benchmark::DoNotOptimize(results); + } +} + +static void CImprovedBench(benchmark::State &state) { + const auto timesteps = OpenCatalog::CreateRandomVector(N, 0.0, 10.0); + auto results = OpenCatalog::CreateUninitializedVector(N); + + for (auto _ : state) { + compute_damped_sinusoid_improved(N, timesteps.data(), AMPLITUDE, + ANGULAR_FREQUENCY, DECAY_RATE, PHASE_SHIFT, + results.data()); + benchmark::DoNotOptimize(results); + } +} + +// A performance impact is expected when performing higher-precision +// calculations +OC_BENCHMARK("PWR037 C Example", CExampleBench); +OC_BENCHMARK("PWR037 C Fixed", CImprovedBench); + +#endif diff --git a/Checks/PWR037/benchmark/example.c b/Checks/PWR037/benchmark/example.c new file mode 100644 index 0000000..6a4762a --- /dev/null +++ b/Checks/PWR037/benchmark/example.c @@ -0,0 +1,17 @@ +// PWR037: Potential precision loss in call to mathematical function + +#include + +// https://en.wikipedia.org/wiki/Damping#Damped_sine_wave +void compute_damped_sinusoid(const int n, const double *timesteps, + const double amplitude, + const double angularFrequency, + const double decayRate, const double phaseShift, + double *results) { + + for (int i = 0; i < n; ++i) { + double exponentialDecay = expf(-decayRate * timesteps[i]); + double angle = angularFrequency * timesteps[i] + phaseShift; + results[i] = amplitude * exponentialDecay * cosf(angle); + } +} diff --git a/Checks/PWR037/benchmark/solution.c b/Checks/PWR037/benchmark/solution.c new file mode 100644 index 0000000..4dc2954 --- /dev/null +++ b/Checks/PWR037/benchmark/solution.c @@ -0,0 +1,18 @@ +// PWR037: Potential precision loss in call to mathematical function + +#include + +// https://en.wikipedia.org/wiki/Damping#Damped_sine_wave +void compute_damped_sinusoid_improved(const int n, const double *timesteps, + const double amplitude, + const double angularFrequency, + const double decayRate, + const double phaseShift, + double *results) { + + for (int i = 0; i < n; ++i) { + double exponentialDecay = exp(-decayRate * timesteps[i]); + double angle = angularFrequency * timesteps[i] + phaseShift; + results[i] = amplitude * exponentialDecay * cos(angle); + } +}