From 16d0fa11658dab4664e0ef91e95a1ee61ed8b54e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 27 Aug 2026 15:28:04 -0500 Subject: [PATCH] [core] Add step_to_accuracy_decimals benchmarks (#18826) --- tests/benchmarks/core/bench_helpers.cpp | 43 ++++++++++++++++ tests/components/core/test_helpers.cpp | 68 +++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/tests/benchmarks/core/bench_helpers.cpp b/tests/benchmarks/core/bench_helpers.cpp index 1ce9101ff6..4a1f3c5bcc 100644 --- a/tests/benchmarks/core/bench_helpers.cpp +++ b/tests/benchmarks/core/bench_helpers.cpp @@ -363,4 +363,47 @@ static void Snprintf_Uint32_Large(benchmark::State &state) { } BENCHMARK(Snprintf_Uint32_Large); +// --- step_to_accuracy_decimals() --- +// Called from climate traits and web_server for every number/climate step. + +static void StepToAccuracyDecimals_Tenth(benchmark::State &state) { + for (auto _ : state) { + int result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += step_to_accuracy_decimals(0.1f); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(StepToAccuracyDecimals_Tenth); + +static void StepToAccuracyDecimals_Whole(benchmark::State &state) { + for (auto _ : state) { + int result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += step_to_accuracy_decimals(1.0f); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(StepToAccuracyDecimals_Whole); + +static void StepToAccuracyDecimals_Mixed(benchmark::State &state) { + static constexpr float steps[] = { + 0.001f, 0.01f, 0.05f, 0.1f, 0.25f, 0.5f, 1.0f, 2.5f, 5.0f, 10.0f, + }; + static constexpr int num_steps = sizeof(steps) / sizeof(steps[0]); + for (auto _ : state) { + int result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += step_to_accuracy_decimals(steps[i % num_steps]); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(StepToAccuracyDecimals_Mixed); + } // namespace esphome::benchmarks diff --git a/tests/components/core/test_helpers.cpp b/tests/components/core/test_helpers.cpp index 3767b24d86..a031dcb36f 100644 --- a/tests/components/core/test_helpers.cpp +++ b/tests/components/core/test_helpers.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "esphome/core/alloc_helpers.h" @@ -280,4 +281,71 @@ TEST(Base64, Rfc4648Vectors) { } } +// --- step_to_accuracy_decimals() --- + +TEST(StepToAccuracyDecimals, TypicalSteps) { + EXPECT_EQ(step_to_accuracy_decimals(0.001f), 3); + EXPECT_EQ(step_to_accuracy_decimals(0.005f), 3); + EXPECT_EQ(step_to_accuracy_decimals(0.01f), 2); + EXPECT_EQ(step_to_accuracy_decimals(0.025f), 3); + EXPECT_EQ(step_to_accuracy_decimals(0.05f), 2); + EXPECT_EQ(step_to_accuracy_decimals(0.1f), 1); + EXPECT_EQ(step_to_accuracy_decimals(0.25f), 2); + EXPECT_EQ(step_to_accuracy_decimals(0.5f), 1); + EXPECT_EQ(step_to_accuracy_decimals(1.5f), 1); + EXPECT_EQ(step_to_accuracy_decimals(2.5f), 1); +} + +TEST(StepToAccuracyDecimals, WholeSteps) { + EXPECT_EQ(step_to_accuracy_decimals(1.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(2.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(5.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(10.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(100.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(1000.0f), 0); +} + +TEST(StepToAccuracyDecimals, FiveSignificantDigits) { + EXPECT_EQ(step_to_accuracy_decimals(1.23456f), 4); + EXPECT_EQ(step_to_accuracy_decimals(12.345f), 3); + EXPECT_EQ(step_to_accuracy_decimals(123.45f), 2); + EXPECT_EQ(step_to_accuracy_decimals(1234.5f), 1); + EXPECT_EQ(step_to_accuracy_decimals(12345.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(0.33333f), 5); + EXPECT_EQ(step_to_accuracy_decimals(0.0001f), 4); +} + +TEST(StepToAccuracyDecimals, TrailingZerosDropped) { + EXPECT_EQ(step_to_accuracy_decimals(0.3f), 1); + EXPECT_EQ(step_to_accuracy_decimals(0.7f), 1); + EXPECT_EQ(step_to_accuracy_decimals(0.125f), 3); + EXPECT_EQ(step_to_accuracy_decimals(0.0625f), 4); +} + +TEST(StepToAccuracyDecimals, RoundsUpToWholeNumber) { + // Rounds to five significant digits first, so this becomes 10 with no decimals. + EXPECT_EQ(step_to_accuracy_decimals(9.999999f), 0); +} + +TEST(StepToAccuracyDecimals, OutsideFixedNotationRange) { + // %.5g prints these in exponent form, so the count comes from parsing "1e-05" or "1.2346e+05". + EXPECT_EQ(step_to_accuracy_decimals(0.00001f), 0); + EXPECT_EQ(step_to_accuracy_decimals(0.000125f), 6); + EXPECT_EQ(step_to_accuracy_decimals(123456.0f), 8); + EXPECT_EQ(step_to_accuracy_decimals(1000000.0f), 0); +} + +TEST(StepToAccuracyDecimals, SignIgnored) { + EXPECT_EQ(step_to_accuracy_decimals(-0.1f), 1); + EXPECT_EQ(step_to_accuracy_decimals(-0.25f), 2); + EXPECT_EQ(step_to_accuracy_decimals(-1.0f), 0); +} + +TEST(StepToAccuracyDecimals, NonFiniteAndZero) { + EXPECT_EQ(step_to_accuracy_decimals(0.0f), 0); + EXPECT_EQ(step_to_accuracy_decimals(NAN), 0); + EXPECT_EQ(step_to_accuracy_decimals(INFINITY), 0); + EXPECT_EQ(step_to_accuracy_decimals(-INFINITY), 0); +} + } // namespace esphome::core::testing