|
1 | 1 | #pragma once
|
2 | 2 | #include <bitset>
|
| 3 | +#include <ranges> |
3 | 4 |
|
4 | 5 | #include <util/generic/queue.h>
|
5 | 6 | #include <util/random/random.h>
|
@@ -201,20 +202,33 @@ TResourceNormalizedValues NormalizeRawValues(const TResourceRawValues& values, c
|
201 | 202 | NMetrics::EResource GetDominantResourceType(const TResourceRawValues& values, const TResourceRawValues& maximum);
|
202 | 203 | NMetrics::EResource GetDominantResourceType(const TResourceNormalizedValues& normValues);
|
203 | 204 |
|
| 205 | +// https://en.wikipedia.org/wiki/Kahan_summation_algorithm |
| 206 | +template<std::ranges::range TRange> |
| 207 | +std::ranges::range_value_t<TRange> StableSum(const TRange& values) { |
| 208 | + using TValue = std::ranges::range_value_t<TRange>; |
| 209 | + TValue sum{}; |
| 210 | + TValue correction{}; |
| 211 | + for (const auto& x : values) { |
| 212 | + TValue y = x - correction; |
| 213 | + TValue tmp = sum + y; |
| 214 | + correction = (tmp - sum) - y; |
| 215 | + sum = tmp; |
| 216 | + } |
| 217 | + return sum; |
| 218 | +} |
| 219 | + |
204 | 220 | template <typename... ResourceTypes>
|
205 | 221 | inline std::tuple<ResourceTypes...> GetStDev(const TVector<std::tuple<ResourceTypes...>>& values) {
|
206 | 222 | std::tuple<ResourceTypes...> sum;
|
207 | 223 | if (values.empty())
|
208 | 224 | return sum;
|
209 |
| - for (const auto& v : values) { |
210 |
| - sum = sum + v; |
211 |
| - } |
| 225 | + sum = StableSum(values); |
212 | 226 | auto mean = sum / values.size();
|
213 |
| - sum = std::tuple<ResourceTypes...>(); |
214 |
| - for (const auto& v : values) { |
215 |
| - auto diff = v - mean; |
216 |
| - sum = sum + diff * diff; |
217 |
| - } |
| 227 | + auto quadraticDev = [&] (const std::tuple<ResourceTypes...>& value) { |
| 228 | + auto diff = value - mean; |
| 229 | + return diff * diff; |
| 230 | + }; |
| 231 | + sum = StableSum(values | std::views::transform(quadraticDev)); |
218 | 232 | auto div = sum / values.size();
|
219 | 233 | auto st_dev = sqrt(div);
|
220 | 234 | return tuple_cast<ResourceTypes...>::cast(st_dev);
|
|
0 commit comments