// Copyright (C) 2021 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #pragma once #include #include #include #include #include #include #include #include #include namespace dittosuite { template T StatisticsGetMin(const std::vector& samples) { if (samples.empty()) LOGF("Cannot compute the min on an empty vector"); return *std::min_element(samples.begin(), samples.end()); } template T StatisticsGetMax(const std::vector& samples) { if (samples.empty()) LOGF("Cannot compute the max on an empty vector"); return *std::max_element(samples.begin(), samples.end()); } template T StatisticsGetMean(const std::vector& samples) { if (samples.empty()) LOGF("Cannot compute the mean on an empty vector"); T result = std::accumulate(samples.begin(), samples.end(), T{}); return result / samples.size(); } template T StatisticsGetMedian(const std::vector& samples) { if (samples.empty()) LOGF("Cannot compute the median on an empty vector"); auto my_vector_copy = samples; auto n = samples.size(); if (n % 2) { // odd number of elements, the median is the element in the middle std::nth_element(my_vector_copy.begin(), my_vector_copy.begin() + n / 2, my_vector_copy.end()); return my_vector_copy[n / 2]; } else { // even number of elements, the median is the average between the two middle elements std::nth_element(my_vector_copy.begin(), my_vector_copy.begin() + n / 2, my_vector_copy.end()); std::nth_element(my_vector_copy.begin(), my_vector_copy.begin() + (n - 1) / 2, my_vector_copy.end()); T result = my_vector_copy[n / 2] + my_vector_copy[(n - 1) / 2]; return result / 2; } } // The standard deviation sd of a population of N samples, where x_i is the // i-th sample and x is the average among all the samples is computed as: // // sd = sqrt( sum( (x_i - x)^2 ) / N ) template double StatisticsGetSd(const std::vector& samples) { if (samples.empty()) LOGF("Cannot compute the sd on an empty vector"); T mean = StatisticsGetMean(samples); double variance; variance = 0.0; for (const auto& s : samples) { double deviation = s - mean; double deviation_square = std::pow(deviation, 2); variance += deviation_square; // TODO(lucialup): add overflow error handling } variance /= samples.size(); return std::sqrt(variance); } } // namespace dittosuite