176 lines
4.9 KiB
C++
176 lines
4.9 KiB
C++
#pragma once
|
|
#include "Defines.h"
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
#include "../inc/tbb/parallel_sort.h"
|
|
#include "../inc/tbb/parallel_reduce.h"
|
|
#include "../inc/tbb/blocked_range.h"
|
|
#include "../inc/glm/glm.hpp"
|
|
#include <stdio.h>
|
|
#include <iostream>
|
|
#include <numeric>
|
|
|
|
class CollectionHelper
|
|
{
|
|
public:
|
|
// Modifies the sequence so that it only contains unique elements. To do this quickly, the elements will be sorted first, meaning the original order is lost.
|
|
template<typename T, typename Compare = std::less<T>>
|
|
inline static void Unique(std::vector<T>& data, Compare comparer = Compare())
|
|
{
|
|
tbb::parallel_sort(data.begin(), data.end(), comparer);
|
|
data.erase(std::unique(data.begin(), data.end()), data.end());
|
|
data.shrink_to_fit();
|
|
}
|
|
|
|
// Modifies the sequence so that it only contains unique elements. To do this quickly, the elements will be sorted first, meaning the original order is lost.
|
|
template<typename T, typename Compare = std::less<T>>
|
|
inline static void UniqueSerial(std::vector<T>& data, Compare comparer = Compare())
|
|
{
|
|
std::sort(data.begin(), data.end(), comparer);
|
|
data.erase(std::unique(data.begin(), data.end()), data.end());
|
|
data.shrink_to_fit();
|
|
}
|
|
|
|
template<typename T, typename Compare = std::less<T>>
|
|
inline static size_t CountUnique(const std::vector<T>& data, Compare comparer = Compare())
|
|
{
|
|
// Copy the data
|
|
std::vector<T> copy(data.size());
|
|
std::copy(data.begin(), data.end(), copy.begin());
|
|
Unique(copy, comparer);
|
|
return copy.size();
|
|
}
|
|
|
|
// Walks through the given data vector and checks if it contains a certain value. O(n) performance.
|
|
template<typename T>
|
|
inline static bool Contains(const std::vector<T>& data, const T& value)
|
|
{
|
|
bool contains = false;
|
|
for (auto mat : data)
|
|
{
|
|
if (mat == value)
|
|
{
|
|
contains = true;
|
|
break;
|
|
}
|
|
}
|
|
return contains;
|
|
}
|
|
|
|
template<typename T, typename Compare = std::less<T>>
|
|
inline static size_t MinIndex(const std::vector<T>& data, Compare comparer = Compare())
|
|
{
|
|
// Finds the minimum value according to some comparer
|
|
return tbb::parallel_reduce(tbb::blocked_range<size_t>(0, data.size()), size_t(0),
|
|
[&](const tbb::blocked_range<size_t>& r, size_t init)
|
|
{
|
|
for (size_t i = r.begin(); i != r.end(); i++)
|
|
if (comparer(data[i], data[init]))
|
|
init = i;
|
|
return init;
|
|
},
|
|
[&](size_t value1, size_t value2)
|
|
{
|
|
if (comparer(data[value1], data[value2]))
|
|
return value1;
|
|
else
|
|
return value2;
|
|
});
|
|
}
|
|
|
|
template<typename T>
|
|
inline static std::unordered_map<T, size_t> GetIndexMap(const std::vector<T>& data)
|
|
{
|
|
std::unordered_map<T, size_t> res;
|
|
for (size_t i = 0; i < data.size(); i++)
|
|
res.insert(std::pair<T, size_t>(data[i], i));
|
|
return res;
|
|
}
|
|
|
|
template<typename T>
|
|
inline static void PrintContents(const std::vector<T>& data, size_t count = 0)
|
|
{
|
|
if (count == 0) count = data.size();
|
|
for (size_t i = 0; i < count; i++)
|
|
{
|
|
std::cout << std::to_string(data[i]).c_str();
|
|
if (i < count - 1)
|
|
std::cout << ", ";
|
|
else
|
|
std::cout << "\n";
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
inline static T Sum(const std::vector<T>& data)
|
|
{
|
|
return std::accumulate(data.begin(), data.end(), (T)0);
|
|
}
|
|
|
|
// Calculates the max given some comparer. Comparer should be a functor that returns true if the first value passed is the biggest value.
|
|
template<typename T, typename Comparer = std::greater<T>>
|
|
inline static T Max(const std::vector<T>& data, Comparer comp = std::greater<T>())
|
|
{
|
|
if (data.empty()) return T();
|
|
T max = data[0];
|
|
for (const T& value : data)
|
|
if (comp(value, max)) max = value;
|
|
return max;
|
|
}
|
|
|
|
template <typename T>
|
|
inline static double CalculateMean(const std::vector<T>& data)
|
|
{
|
|
return ((double)Sum(data)) / ((double)data.size());
|
|
}
|
|
|
|
template <typename T>
|
|
inline static double CalculateVariance(const std::vector<T>& data, double mean)
|
|
{
|
|
double variance = 0;
|
|
for (T v : data)
|
|
{
|
|
double meanDiff = ((double)v) - mean;
|
|
variance += meanDiff * meanDiff;
|
|
}
|
|
variance /= (double)data.size();
|
|
return variance;
|
|
}
|
|
|
|
template <typename T>
|
|
inline static double CalculateVariance(const std::vector<T>& data)
|
|
{
|
|
return CalculateVariance(data, CalculateMean(data));
|
|
}
|
|
|
|
template <typename T>
|
|
inline static T CalculateMedian(const std::vector<T>& data)
|
|
{
|
|
std::vector<T> dataCopy(data.size());
|
|
std::copy(data.begin(), data.end(), dataCopy.begin());
|
|
tbb::parallel_sort(dataCopy.begin(), dataCopy.end());
|
|
return dataCopy[dataCopy.size() / 2];
|
|
}
|
|
|
|
template <typename T>
|
|
inline static size_t Count(const std::vector<T>& data, const T& value)
|
|
{
|
|
size_t count = 0;
|
|
for (T v : data) if (v == value) count++;
|
|
return count;
|
|
}
|
|
|
|
template <typename T>
|
|
inline static void PrintStats(const std::vector<T>& data)
|
|
{
|
|
|
|
double mean = CalculateMean(data);
|
|
unsigned32 zeroCount = (unsigned32)Count(data, 0);
|
|
double variance = CalculateVariance(data);
|
|
T median = CalculateMedian(data);
|
|
|
|
printf("Size: %llu, Zero count: %u, Mean: %f, Median: %i, Variance: %f\n", data.size(), zeroCount, mean, median, variance);
|
|
}
|
|
};
|
|
|