mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-17 19:05:42 +00:00
102 lines
2.8 KiB
C++
102 lines
2.8 KiB
C++
/*
|
|
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Affero General Public License as published by the
|
|
* Free Software Foundation; either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef _MATH_UTIL_H
|
|
#define _MATH_UTIL_H
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <numeric>
|
|
#include <vector>
|
|
|
|
// based on https://stackoverflow.com/questions/7616511/calculate-mean-and-standard-deviation-from-a-vector-of-samples-in-c-using-boos/12405793#comment32490316_12405793
|
|
template <typename Container, typename T = typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>
|
|
inline T standard_deviation(Container&& c)
|
|
{
|
|
auto b = std::begin(c), e = std::end(c);
|
|
auto size = std::distance(b, e);
|
|
auto sum = std::accumulate(b, e, T());
|
|
auto mean = sum / size;
|
|
|
|
if (size == 1)
|
|
{
|
|
return (T) 0;
|
|
}
|
|
|
|
T accum = T();
|
|
for (const auto d : c)
|
|
{
|
|
accum += (d - mean) * (d - mean);
|
|
}
|
|
return std::sqrt(accum / (size - 1));
|
|
}
|
|
|
|
template <typename Container, typename T = typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>
|
|
inline T mean(Container&& c)
|
|
{
|
|
auto b = std::begin(c), e = std::end(c);
|
|
auto size = std::distance(b, e);
|
|
auto sum = std::accumulate(b, e, T());
|
|
return sum / size;
|
|
}
|
|
|
|
// based off https://www.geeksforgeeks.org/finding-median-of-unsorted-array-in-linear-time-using-c-stl/
|
|
template <typename T>
|
|
inline T median(std::vector<T> a)
|
|
{
|
|
size_t n = a.size();
|
|
// If size of the arr[] is even
|
|
if (n % 2 == 0)
|
|
{
|
|
|
|
// Applying nth_element
|
|
// on n/2th index
|
|
std::nth_element(a.begin(),
|
|
a.begin() + n / 2,
|
|
a.end());
|
|
|
|
// Applying nth_element
|
|
// on (n-1)/2 th index
|
|
std::nth_element(a.begin(),
|
|
a.begin() + (n - 1) / 2,
|
|
a.end());
|
|
|
|
// Find the average of value at
|
|
// index N/2 and (N-1)/2
|
|
return (T)(a[(n - 1) / 2]
|
|
+ a[n / 2])
|
|
/ 2.0;
|
|
}
|
|
|
|
// If size of the arr[] is odd
|
|
else
|
|
{
|
|
|
|
// Applying nth_element
|
|
// on n/2
|
|
std::nth_element(a.begin(),
|
|
a.begin() + n / 2,
|
|
a.end());
|
|
|
|
// Value at index (N/2)th
|
|
// is the median
|
|
return (T)a[n / 2];
|
|
}
|
|
}
|
|
|
|
#endif
|