96 lines
3.0 KiB
C++
96 lines
3.0 KiB
C++
// 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
|