Files
CDAG/Research/core/CollectionHelper.h

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);
}
};