Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarAlgorithm.hpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarAlgorithm.hpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/core/StarAlgorithm.hpp')
-rw-r--r--source/core/StarAlgorithm.hpp667
1 files changed, 667 insertions, 0 deletions
diff --git a/source/core/StarAlgorithm.hpp b/source/core/StarAlgorithm.hpp
new file mode 100644
index 0000000..331f653
--- /dev/null
+++ b/source/core/StarAlgorithm.hpp
@@ -0,0 +1,667 @@
+#ifndef STAR_ALGORITHM_HPP
+#define STAR_ALGORITHM_HPP
+
+#include <type_traits>
+#include <vector>
+#include <iterator>
+
+#include "StarException.hpp"
+
+namespace Star {
+
+// Function that does nothing and takes any number of arguments
+template <typename... T>
+void nothing(T&&...) {}
+
+// Functional constructor call / casting.
+template <typename ToType>
+struct construct {
+ template <typename... FromTypes>
+ ToType operator()(FromTypes&&... fromTypes) const {
+ return ToType(forward<FromTypes>(fromTypes)...);
+ }
+};
+
+struct identity {
+ template <typename U>
+ constexpr decltype(auto) operator()(U&& v) const {
+ return std::forward<U>(v);
+ }
+};
+
+template <typename Func>
+struct SwallowReturn {
+ template <typename... T>
+ void operator()(T&&... args) {
+ func(forward<T>(args)...);
+ }
+
+ Func func;
+};
+
+template <typename Func>
+SwallowReturn<Func> swallow(Func f) {
+ return SwallowReturn<Func>{move(f)};
+}
+
+struct Empty {
+ bool operator==(Empty const) const {
+ return true;
+ }
+
+ bool operator<(Empty const) const {
+ return false;
+ }
+};
+
+// Compose arbitrary functions
+template <typename FirstFunction, typename SecondFunction>
+struct FunctionComposer {
+ FirstFunction f1;
+ SecondFunction f2;
+
+ template <typename... T>
+ decltype(auto) operator()(T&&... args) {
+ return f1(f2(forward<T>(args)...));
+ }
+};
+
+template <typename FirstFunction, typename SecondFunction>
+decltype(auto) compose(FirstFunction&& firstFunction, SecondFunction&& secondFunction) {
+ return FunctionComposer<FirstFunction, SecondFunction>{move(forward<FirstFunction>(firstFunction)), move(forward<SecondFunction>(secondFunction))};
+}
+
+template <typename FirstFunction, typename SecondFunction, typename ThirdFunction, typename... RestFunctions>
+decltype(auto) compose(FirstFunction firstFunction, SecondFunction secondFunction, ThirdFunction thirdFunction, RestFunctions... restFunctions) {
+ return compose(forward<FirstFunction>(firstFunction), compose(forward<SecondFunction>(secondFunction), compose(forward<ThirdFunction>(thirdFunction), forward<RestFunctions>(restFunctions)...)));
+}
+
+template <typename Container, typename Value, typename Function>
+Value fold(Container const& l, Value v, Function f) {
+ auto i = l.begin();
+ auto e = l.end();
+ while (i != e) {
+ v = f(v, *i);
+ ++i;
+ }
+ return v;
+}
+
+// Like fold, but returns default value when container is empty.
+template <typename Container, typename Function>
+typename Container::value_type fold1(Container const& l, Function f) {
+ typename Container::value_type res = {};
+ typename Container::const_iterator i = l.begin();
+ typename Container::const_iterator e = l.end();
+
+ if (i == e)
+ return res;
+
+ res = *i;
+ ++i;
+ while (i != e) {
+ res = f(res, *i);
+ ++i;
+ }
+ return res;
+}
+
+// Return intersection of sorted containers.
+template <typename Container>
+Container intersect(Container const& a, Container const& b) {
+ Container r;
+ std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::inserter(r, r.end()));
+ return r;
+}
+
+template <typename MapType1, typename MapType2>
+bool mapMerge(MapType1& targetMap, MapType2 const& sourceMap, bool overwrite = false) {
+ bool noCommonKeys = true;
+ for (auto i = sourceMap.begin(); i != sourceMap.end(); ++i) {
+ auto res = targetMap.insert(*i);
+ if (!res.second) {
+ noCommonKeys = false;
+ if (overwrite)
+ res.first->second = i->second;
+ }
+ }
+ return noCommonKeys;
+}
+
+template <typename MapType1, typename MapType2>
+bool mapsEqual(MapType1 const& m1, MapType2 const& m2) {
+ if (&m1 == &m2)
+ return true;
+
+ if (m1.size() != m2.size())
+ return false;
+
+ for (auto const& m1pair : m1) {
+ auto m2it = m2.find(m1pair.first);
+ if (m2it == m2.end() || !(m2it->second == m1pair.second))
+ return false;
+ }
+
+ return true;
+}
+
+template <typename Container, typename Filter>
+void filter(Container& container, Filter&& filter) {
+ auto p = std::begin(container);
+ while (p != std::end(container)) {
+ if (!filter(*p))
+ p = container.erase(p);
+ else
+ ++p;
+ }
+}
+
+template <typename OutContainer, typename InContainer, typename Filter>
+OutContainer filtered(InContainer const& input, Filter&& filter) {
+ OutContainer out;
+ auto p = std::begin(input);
+ while (p != std::end(input)) {
+ if (filter(*p))
+ out.insert(out.end(), *p);
+ ++p;
+ }
+ return out;
+}
+
+template <typename Container, typename Cond>
+void eraseWhere(Container& container, Cond&& cond) {
+ auto p = std::begin(container);
+ while (p != std::end(container)) {
+ if (cond(*p))
+ p = container.erase(p);
+ else
+ ++p;
+ }
+}
+
+template <typename Container, typename Compare>
+void sort(Container& c, Compare comp) {
+ std::sort(c.begin(), c.end(), comp);
+}
+
+template <typename Container, typename Compare>
+void stableSort(Container& c, Compare comp) {
+ std::stable_sort(c.begin(), c.end(), comp);
+}
+
+template <typename Container>
+void sort(Container& c) {
+ std::sort(c.begin(), c.end(), std::less<typename Container::value_type>());
+}
+
+template <typename Container>
+void stableSort(Container& c) {
+ std::stable_sort(c.begin(), c.end(), std::less<typename Container::value_type>());
+}
+
+template <typename Container, typename Compare>
+Container sorted(Container const& c, Compare comp) {
+ auto c2 = c;
+ sort(c2, comp);
+ return c2;
+}
+
+template <typename Container, typename Compare>
+Container stableSorted(Container const& c, Compare comp) {
+ auto c2 = c;
+ sort(c2, comp);
+ return c2;
+}
+
+template <typename Container>
+Container sorted(Container const& c) {
+ auto c2 = c;
+ sort(c2);
+ return c2;
+}
+
+template <typename Container>
+Container stableSorted(Container const& c) {
+ auto c2 = c;
+ sort(c2);
+ return c2;
+}
+
+// Sort a container by the output of a computed value. The computed value is
+// only computed *once* per item in the container, which is useful both for
+// when the computed value is costly, and to avoid sorting instability with
+// floating point values. Container must have size() and operator[], and also
+// must be constructable with Container(size_t).
+template <typename Container, typename Getter>
+void sortByComputedValue(Container& container, Getter&& valueGetter, bool stable = false) {
+ typedef typename Container::value_type ContainerValue;
+ typedef decltype(valueGetter(ContainerValue())) ComputedValue;
+ typedef std::pair<ComputedValue, size_t> ComputedPair;
+
+ size_t containerSize = container.size();
+
+ if (containerSize <= 1)
+ return;
+
+ std::vector<ComputedPair> work(containerSize);
+ for (size_t i = 0; i < containerSize; ++i)
+ work[i] = {valueGetter(container[i]), i};
+
+ auto compare = [](ComputedPair const& a, ComputedPair const& b) { return a.first < b.first; };
+
+ // Sort the comptued values and the associated indexes
+ if (stable)
+ stableSort(work, compare);
+ else
+ sort(work, compare);
+
+ Container result(containerSize);
+ for (size_t i = 0; i < containerSize; ++i)
+ swap(result[i], container[work[i].second]);
+
+ swap(container, result);
+}
+
+template <typename Container, typename Getter>
+void stableSortByComputedValue(Container& container, Getter&& valueGetter) {
+ return sortByComputedValue(container, forward<Getter>(valueGetter), true);
+}
+
+template <typename Container>
+void shuffle(Container& c) {
+ std::random_shuffle(c.begin(), c.end());
+}
+
+template <typename Container>
+void reverse(Container& c) {
+ std::reverse(c.begin(), c.end());
+}
+
+template <typename Container>
+Container reverseCopy(Container c) {
+ reverse(c);
+ return c;
+}
+
+template <typename T>
+T copy(T c) {
+ return c;
+}
+
+template <typename Container>
+typename Container::value_type sum(Container const& cont) {
+ return fold1(cont, std::plus<typename Container::value_type>());
+}
+
+template <typename Container>
+typename Container::value_type product(Container const& cont) {
+ return fold1(cont, std::multiplies<typename Container::value_type>());
+}
+
+template <typename OutContainer, typename InContainer, typename Function>
+void transformInto(OutContainer& outContainer, InContainer&& inContainer, Function&& function) {
+ for (auto&& elem : inContainer) {
+ if (std::is_rvalue_reference<InContainer&&>::value)
+ outContainer.insert(outContainer.end(), function(move(elem)));
+ else
+ outContainer.insert(outContainer.end(), function(elem));
+ }
+}
+
+template <typename OutContainer, typename InContainer, typename Function>
+OutContainer transform(InContainer&& container, Function&& function) {
+ OutContainer res;
+ transformInto(res, forward<InContainer>(container), forward<Function>(function));
+ return res;
+}
+
+template <typename OutputContainer, typename Function, typename Container1, typename Container2>
+OutputContainer zipWith(Function&& function, Container1 const& cont1, Container2 const& cont2) {
+ auto it1 = cont1.begin();
+ auto it2 = cont2.begin();
+
+ OutputContainer out;
+ while (it1 != cont1.end() && it2 != cont2.end()) {
+ out.insert(out.end(), function(*it1, *it2));
+ ++it1;
+ ++it2;
+ }
+
+ return out;
+}
+
+// Moves the given value and into an rvalue. Works whether or not the type has
+// a valid move constructor or not. Always leaves the given value in its
+// default constructed state.
+template <typename T>
+T take(T& t) {
+ T t2 = move(t);
+ t = T();
+ return t2;
+}
+
+template <typename Container1, typename Container2>
+bool containersEqual(Container1 const& cont1, Container2 const& cont2) {
+ if (cont1.size() != cont2.size())
+ return false;
+ else
+ return std::equal(cont1.begin(), cont1.end(), cont2.begin());
+}
+
+// Wraps a unary function to produce an output iterator
+template <typename UnaryFunction>
+class FunctionOutputIterator {
+public:
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ class OutputProxy {
+ public:
+ OutputProxy(UnaryFunction& f)
+ : m_function(f) {}
+
+ template <typename T>
+ OutputProxy& operator=(T&& value) {
+ m_function(forward<T>(value));
+ return *this;
+ }
+
+ private:
+ UnaryFunction& m_function;
+ };
+
+ explicit FunctionOutputIterator(UnaryFunction f = UnaryFunction())
+ : m_function(move(f)) {}
+
+ OutputProxy operator*() {
+ return OutputProxy(m_function);
+ }
+
+ FunctionOutputIterator& operator++() {
+ return *this;
+ }
+
+ FunctionOutputIterator operator++(int) {
+ return *this;
+ }
+
+private:
+ UnaryFunction m_function;
+};
+
+template <typename UnaryFunction>
+FunctionOutputIterator<UnaryFunction> makeFunctionOutputIterator(UnaryFunction f) {
+ return FunctionOutputIterator<UnaryFunction>(move(f));
+}
+
+// Wraps a nullary function to produce an input iterator
+template <typename NullaryFunction>
+class FunctionInputIterator {
+public:
+ typedef std::output_iterator_tag iterator_category;
+ typedef void value_type;
+ typedef void difference_type;
+ typedef void pointer;
+ typedef void reference;
+
+ typedef typename std::result_of<NullaryFunction()>::type FunctionReturnType;
+
+ explicit FunctionInputIterator(NullaryFunction f = {})
+ : m_function(move(f)) {}
+
+ FunctionReturnType operator*() {
+ return m_function();
+ }
+
+ FunctionInputIterator& operator++() {
+ return *this;
+ }
+
+ FunctionInputIterator operator++(int) {
+ return *this;
+ }
+
+private:
+ NullaryFunction m_function;
+};
+
+template <typename NullaryFunction>
+FunctionInputIterator<NullaryFunction> makeFunctionInputIterator(NullaryFunction f) {
+ return FunctionInputIterator<NullaryFunction>(move(f));
+}
+
+template <typename Iterable>
+struct ReverseWrapper {
+private:
+ Iterable& m_iterable;
+
+public:
+ ReverseWrapper(Iterable& iterable) : m_iterable(iterable) {}
+
+ decltype(auto) begin() const {
+ return std::rbegin(m_iterable);
+ }
+
+ decltype(auto) end() const {
+ return std::rend(m_iterable);
+ }
+};
+
+template <typename Iterable>
+ReverseWrapper<Iterable> reverseIterate(Iterable& list) {
+ return ReverseWrapper<Iterable>(list);
+}
+
+template <typename Functor>
+class FinallyGuard {
+public:
+ FinallyGuard(Functor functor) : functor(move(functor)), dismiss(false) {}
+
+ FinallyGuard(FinallyGuard&& o) : functor(move(o.functor)), dismiss(o.dismiss) {
+ o.cancel();
+ }
+
+ FinallyGuard& operator=(FinallyGuard&& o) {
+ functor = move(o.functor);
+ dismiss = o.dismiss;
+ o.cancel();
+ return *this;
+ }
+
+ ~FinallyGuard() {
+ if (!dismiss)
+ functor();
+ }
+
+ void cancel() {
+ dismiss = true;
+ }
+
+private:
+ Functor functor;
+ bool dismiss;
+};
+
+template <typename Functor>
+FinallyGuard<typename std::decay<Functor>::type> finally(Functor&& f) {
+ return FinallyGuard<Functor>(forward<Functor>(f));
+}
+
+// Generates compile time sequences of indexes from MinIndex to MaxIndex
+
+template <size_t...>
+struct IndexSequence {};
+
+template <size_t Min, size_t N, size_t... S>
+struct GenIndexSequence : GenIndexSequence<Min, N - 1, N - 1, S...> {};
+
+template <size_t Min, size_t... S>
+struct GenIndexSequence<Min, Min, S...> {
+ typedef IndexSequence<S...> type;
+};
+
+// Apply a tuple as individual arguments to a function
+
+template <typename Function, typename Tuple, size_t... Indexes>
+decltype(auto) tupleUnpackFunctionIndexes(Function&& function, Tuple&& args, IndexSequence<Indexes...> const&) {
+ return function(get<Indexes>(forward<Tuple>(args))...);
+}
+
+template <typename Function, typename Tuple>
+decltype(auto) tupleUnpackFunction(Function&& function, Tuple&& args) {
+ return tupleUnpackFunctionIndexes<Function, Tuple>(forward<Function>(function), forward<Tuple>(args),
+ typename GenIndexSequence<0, std::tuple_size<typename std::decay<Tuple>::type>::value>::type());
+}
+
+// Apply a function to every element of a tuple. This will NOT happen in a
+// predictable order!
+
+template <typename Function, typename Tuple, size_t... Indexes>
+decltype(auto) tupleApplyFunctionIndexes(Function&& function, Tuple&& args, IndexSequence<Indexes...> const&) {
+ return make_tuple(function(get<Indexes>(forward<Tuple>(args)))...);
+}
+
+template <typename Function, typename Tuple>
+decltype(auto) tupleApplyFunction(Function&& function, Tuple&& args) {
+ return tupleApplyFunctionIndexes<Function, Tuple>(forward<Function>(function), forward<Tuple>(args),
+ typename GenIndexSequence<0, std::tuple_size<typename std::decay<Tuple>::type>::value>::type());
+}
+
+// Use this version if you do not care about the return value of the function
+// or your function returns void. This version DOES happen in a predictable
+// order, first argument first, last argument last.
+
+template <typename Function, typename Tuple>
+void tupleCallFunctionCaller(Function&&, Tuple&&) {}
+
+template <typename Tuple, typename Function, typename First, typename... Rest>
+void tupleCallFunctionCaller(Tuple&& t, Function&& function) {
+ tupleCallFunctionCaller<Tuple, Function, Rest...>(forward<Tuple>(t), forward<Function>(function));
+ function(get<sizeof...(Rest)>(forward<Tuple>(t)));
+}
+
+template <typename Tuple, typename Function, typename... T>
+void tupleCallFunctionExpander(Tuple&& t, Function&& function, tuple<T...> const&) {
+ tupleCallFunctionCaller<Tuple, Function, T...>(forward<Tuple>(t), forward<Function>(function));
+}
+
+template <typename Tuple, typename Function>
+void tupleCallFunction(Tuple&& t, Function&& function) {
+ tupleCallFunctionExpander<Tuple, Function>(forward<Tuple>(t), forward<Function>(function), forward<Tuple>(t));
+}
+
+// Get a subset of a tuple
+
+template <typename Tuple, size_t... Indexes>
+decltype(auto) subTupleIndexes(Tuple&& t, IndexSequence<Indexes...> const&) {
+ return make_tuple(get<Indexes>(forward<Tuple>(t))...);
+}
+
+template <size_t Min, size_t Size, typename Tuple>
+decltype(auto) subTuple(Tuple&& t) {
+ return subTupleIndexes(forward<Tuple>(t), GenIndexSequence<Min, Size>::type());
+}
+
+template <size_t Trim, typename Tuple>
+decltype(auto) trimTuple(Tuple&& t) {
+ return subTupleIndexes(forward<Tuple>(t), typename GenIndexSequence<Trim, std::tuple_size<typename std::decay<Tuple>::type>::value>::type());
+}
+
+// Unpack a parameter expansion into a container
+
+template <typename Container>
+void unpackVariadicImpl(Container&) {}
+
+template <typename Container, typename TFirst, typename... TRest>
+void unpackVariadicImpl(Container& container, TFirst&& tfirst, TRest&&... trest) {
+ container.insert(container.end(), forward<TFirst>(tfirst));
+ unpackVariadicImpl(container, forward<TRest>(trest)...);
+}
+
+template <typename Container, typename... T>
+Container unpackVariadic(T&&... t) {
+ Container c;
+ unpackVariadicImpl(c, forward<T>(t)...);
+ return c;
+}
+
+// Call a function on each entry in a variadic parameter set
+
+template <typename Function>
+void callFunctionVariadic(Function&&) {}
+
+template <typename Function, typename Arg1, typename... ArgRest>
+void callFunctionVariadic(Function&& function, Arg1&& arg1, ArgRest&&... argRest) {
+ function(arg1);
+ callFunctionVariadic(forward<Function>(function), forward<ArgRest>(argRest)...);
+}
+
+template <typename... Rest>
+struct VariadicTypedef;
+
+template <>
+struct VariadicTypedef<> {};
+
+template <typename FirstT, typename... RestT>
+struct VariadicTypedef<FirstT, RestT...> {
+ typedef FirstT First;
+ typedef VariadicTypedef<RestT...> Rest;
+};
+
+// For generic types, directly use the result of the signature of its
+// 'operator()'
+template <typename T>
+struct FunctionTraits : public FunctionTraits<decltype(&T::operator())> {};
+
+template <typename ReturnType, typename... ArgsTypes>
+struct FunctionTraits<ReturnType(ArgsTypes...)> {
+ // arity is the number of arguments.
+ static constexpr size_t Arity = sizeof...(ArgsTypes);
+
+ typedef ReturnType Return;
+
+ typedef VariadicTypedef<ArgsTypes...> Args;
+ typedef tuple<ArgsTypes...> ArgTuple;
+
+ template <size_t i>
+ struct Arg {
+ // the i-th argument is equivalent to the i-th tuple element of a tuple
+ // composed of those arguments.
+ typedef typename tuple_element<i, ArgTuple>::type type;
+ };
+};
+
+template <typename ReturnType, typename... Args>
+struct FunctionTraits<ReturnType (*)(Args...)> : public FunctionTraits<ReturnType(Args...)> {};
+
+template <typename FunctionType>
+struct FunctionTraits<std::function<FunctionType>> : public FunctionTraits<FunctionType> {};
+
+template <typename ClassType, typename ReturnType, typename... Args>
+struct FunctionTraits<ReturnType (ClassType::*)(Args...)> : public FunctionTraits<ReturnType(Args...)> {
+ typedef ClassType& OwnerType;
+};
+
+template <typename ClassType, typename ReturnType, typename... Args>
+struct FunctionTraits<ReturnType (ClassType::*)(Args...) const> : public FunctionTraits<ReturnType(Args...)> {
+ typedef const ClassType& OwnerType;
+};
+
+template <typename T>
+struct FunctionTraits<T&> : public FunctionTraits<T> {};
+
+template <typename T>
+struct FunctionTraits<T const&> : public FunctionTraits<T> {};
+
+template <typename T>
+struct FunctionTraits<T&&> : public FunctionTraits<T> {};
+
+template <typename T>
+struct FunctionTraits<T const&&> : public FunctionTraits<T> {};
+
+}
+
+#endif