stats.cc (3649B)
1 // Copyright 2024 Google LLC 2 // SPDX-License-Identifier: Apache-2.0 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // https://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #include "hwy/stats.h" 17 18 #include <stdio.h> 19 20 #include <algorithm> // std::min 21 #include <string> 22 23 #include "hwy/base.h" // HWY_ASSERT 24 25 namespace hwy { 26 27 void Stats::Assimilate(const Stats& other) { 28 const int64_t total_n = n_ + other.n_; 29 if (total_n == 0) return; // Nothing to do; prevents div by zero. 30 31 min_ = std::min(min_, other.min_); 32 max_ = std::max(max_, other.max_); 33 34 sum_log_ += other.sum_log_; 35 36 const double product_n = n_ * other.n_; 37 const double n2 = n_ * n_; 38 const double other_n2 = other.n_ * other.n_; 39 const int64_t total_n2 = total_n * total_n; 40 const double total_n3 = static_cast<double>(total_n2) * total_n; 41 // Precompute reciprocal for speed - used at least twice. 42 const double inv_total_n = 1.0 / total_n; 43 const double inv_total_n2 = 1.0 / total_n2; 44 45 const double delta = other.m1_ - m1_; 46 const double delta2 = delta * delta; 47 const double delta3 = delta * delta2; 48 const double delta4 = delta2 * delta2; 49 50 m1_ = (n_ * m1_ + other.n_ * other.m1_) * inv_total_n; 51 52 const double new_m2 = m2_ + other.m2_ + delta2 * product_n * inv_total_n; 53 54 const double new_m3 = 55 m3_ + other.m3_ + delta3 * product_n * (n_ - other.n_) * inv_total_n2 + 56 3.0 * delta * (n_ * other.m2_ - other.n_ * m2_) * inv_total_n; 57 58 m4_ += other.m4_ + 59 delta4 * product_n * (n2 - product_n + other_n2) / total_n3 + 60 6.0 * delta2 * (n2 * other.m2_ + other_n2 * m2_) * inv_total_n2 + 61 4.0 * delta * (n_ * other.m3_ - other.n_ * m3_) * inv_total_n; 62 63 m2_ = new_m2; 64 m3_ = new_m3; 65 n_ = total_n; 66 } 67 68 std::string Stats::ToString(int exclude) const { 69 if (Count() == 0) return std::string("(none)"); 70 71 char buf[300]; 72 size_t pos = 0; 73 int ret; // snprintf - bytes written or negative for error. 74 75 if ((exclude & kNoCount) == 0) { 76 ret = snprintf(buf + pos, sizeof(buf) - pos, "Count=%9zu ", 77 static_cast<size_t>(Count())); 78 HWY_ASSERT(ret > 0); 79 pos += ret; 80 } 81 82 if ((exclude & kNoMeanSD) == 0) { 83 const float sd = StandardDeviation(); 84 if (sd > 100) { 85 ret = snprintf(buf + pos, sizeof(buf) - pos, "Mean=%8.2e SD=%7.1e ", 86 Mean(), sd); 87 } else { 88 ret = snprintf(buf + pos, sizeof(buf) - pos, "Mean=%8.6e SD=%7.5e ", 89 Mean(), sd); 90 } 91 HWY_ASSERT(ret > 0); 92 pos += ret; 93 } 94 95 if ((exclude & kNoMinMax) == 0) { 96 ret = snprintf(buf + pos, sizeof(buf) - pos, "Min=%8.5e Max=%8.5e ", 97 static_cast<double>(Min()), static_cast<double>(Max())); 98 HWY_ASSERT(ret > 0); 99 pos += ret; 100 } 101 102 if ((exclude & kNoSkewKurt) == 0) { 103 ret = snprintf(buf + pos, sizeof(buf) - pos, "Skew=%5.2f Kurt=%7.2f ", 104 Skewness(), Kurtosis()); 105 HWY_ASSERT(ret > 0); 106 pos += ret; 107 } 108 109 if ((exclude & kNoGeomean) == 0) { 110 ret = snprintf(buf + pos, sizeof(buf) - pos, "GeoMean=%9.6f ", 111 GeometricMean()); 112 HWY_ASSERT(ret > 0); 113 pos += ret; 114 } 115 116 HWY_ASSERT(pos < sizeof(buf)); 117 return buf; 118 } 119 120 } // namespace hwy