blob: fd7ab6e74cf89cb79ae40f5c9a029e8ed4bfdd25 [file] [log] [blame]
// 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 <ditto/logger.h>
#include <ditto/sampler.h>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <memory>
#include <numeric>
#include <string>
#include <vector>
namespace dittosuite {
template <class T>
T StatisticsGetMin(const std::vector<T>& samples) {
if (samples.empty()) LOGF("Cannot compute the min on an empty vector");
return *std::min_element(samples.begin(), samples.end());
}
template <class T>
T StatisticsGetMax(const std::vector<T>& samples) {
if (samples.empty()) LOGF("Cannot compute the max on an empty vector");
return *std::max_element(samples.begin(), samples.end());
}
template <class T>
T StatisticsGetMean(const std::vector<T>& 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 <class T>
T StatisticsGetMedian(const std::vector<T>& 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 <class T>
double StatisticsGetSd(const std::vector<T>& 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