v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
603
source/core/StarPythonic.hpp
Normal file
603
source/core/StarPythonic.hpp
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
#ifndef STAR_PYTHONIC_HPP
|
||||
#define STAR_PYTHONIC_HPP
|
||||
|
||||
#include "StarAlgorithm.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
// any and all
|
||||
|
||||
template <typename Iterator, typename Functor>
|
||||
bool any(Iterator iterBegin, Iterator iterEnd, Functor const& f) {
|
||||
for (; iterBegin != iterEnd; iterBegin++)
|
||||
if (f(*iterBegin))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
bool any(Iterator const& iterBegin, Iterator const& iterEnd) {
|
||||
typedef typename std::iterator_traits<Iterator>::value_type IteratorValue;
|
||||
std::function<bool(IteratorValue)> compare = [](IteratorValue const& i) { return (bool)i; };
|
||||
return any(iterBegin, iterEnd, compare);
|
||||
}
|
||||
|
||||
template <typename Iterable, typename Functor>
|
||||
bool any(Iterable const& iter, Functor const& f) {
|
||||
return any(std::begin(iter), std::end(iter), f);
|
||||
}
|
||||
|
||||
template <typename Iterable>
|
||||
bool any(Iterable const& iter) {
|
||||
typedef decltype(*std::begin(iter)) IteratorValue;
|
||||
std::function<bool(IteratorValue)> compare = [](IteratorValue const& i) { return (bool)i; };
|
||||
return any(std::begin(iter), std::end(iter), compare);
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Functor>
|
||||
bool all(Iterator iterBegin, Iterator iterEnd, Functor const& f) {
|
||||
for (; iterBegin != iterEnd; iterBegin++)
|
||||
if (!f(*iterBegin))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
bool all(Iterator const& iterBegin, Iterator const& iterEnd) {
|
||||
typedef typename std::iterator_traits<Iterator>::value_type IteratorValue;
|
||||
std::function<bool(IteratorValue)> compare = [](IteratorValue const& i) { return (bool)i; };
|
||||
return all(iterBegin, iterEnd, compare);
|
||||
}
|
||||
|
||||
template <typename Iterable, typename Functor>
|
||||
bool all(Iterable const& iter, Functor const& f) {
|
||||
return all(std::begin(iter), std::end(iter), f);
|
||||
}
|
||||
|
||||
template <typename Iterable>
|
||||
bool all(Iterable const& iter) {
|
||||
typedef decltype(*std::begin(iter)) IteratorValue;
|
||||
std::function<bool(IteratorValue)> compare = [](IteratorValue const& i) { return (bool)i; };
|
||||
return all(std::begin(iter), std::end(iter), compare);
|
||||
}
|
||||
|
||||
// Python style container slicing
|
||||
|
||||
struct SliceIndex {
|
||||
SliceIndex() : index(0), given(false) {}
|
||||
SliceIndex(int i) : index(i), given(true) {}
|
||||
|
||||
int index;
|
||||
bool given;
|
||||
};
|
||||
|
||||
SliceIndex const SliceNil = SliceIndex();
|
||||
|
||||
// T must have operator[](int), size(), and
|
||||
// push_back(typeof T::operator[](int()))
|
||||
template <typename Res, typename In>
|
||||
Res slice(In const& r, SliceIndex a, SliceIndex b = SliceIndex(), int j = 1) {
|
||||
int size = (int)r.size();
|
||||
int start, end;
|
||||
|
||||
// Throw exception on j == 0?
|
||||
if (j == 0 || size == 0)
|
||||
return Res();
|
||||
|
||||
if (!a.given) {
|
||||
if (j > 0)
|
||||
start = 0;
|
||||
else
|
||||
start = size - 1;
|
||||
} else if (a.index < 0) {
|
||||
if (-a.index > size - 1)
|
||||
start = 0;
|
||||
else
|
||||
start = size - -a.index;
|
||||
} else {
|
||||
if (a.index > size)
|
||||
start = size;
|
||||
else
|
||||
start = a.index;
|
||||
}
|
||||
|
||||
if (!b.given) {
|
||||
if (j > 0)
|
||||
end = size;
|
||||
else
|
||||
end = -1;
|
||||
} else if (b.index < 0) {
|
||||
if (-b.index > size - 1) {
|
||||
end = -1;
|
||||
} else {
|
||||
end = size - -b.index;
|
||||
}
|
||||
} else {
|
||||
if (b.index > size - 1) {
|
||||
end = size;
|
||||
} else {
|
||||
end = b.index;
|
||||
}
|
||||
}
|
||||
|
||||
if (start < end && j < 0)
|
||||
return Res();
|
||||
if (start > end && j > 0)
|
||||
return Res();
|
||||
|
||||
Res returnSlice;
|
||||
int i;
|
||||
for (i = start; i < end; i += j)
|
||||
returnSlice.push_back(r[i]);
|
||||
|
||||
return returnSlice;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T slice(T const& r, SliceIndex a, SliceIndex b = SliceIndex(), int j = 1) {
|
||||
return slice<T, T>(r, a, b, j);
|
||||
}
|
||||
|
||||
// ZIP
|
||||
|
||||
// Wraps a regular iterator and returns a singleton tuple, as well as
|
||||
// supporting the iterator protocol that the zip iterator code expects.
|
||||
template <typename IteratorT>
|
||||
class ZipWrapperIterator {
|
||||
private:
|
||||
IteratorT current;
|
||||
IteratorT last;
|
||||
bool atEnd;
|
||||
|
||||
public:
|
||||
typedef IteratorT Iterator;
|
||||
typedef decltype(*std::declval<Iterator>()) IteratorValue;
|
||||
typedef tuple<IteratorValue> value_type;
|
||||
|
||||
ZipWrapperIterator() : atEnd(true) {}
|
||||
|
||||
ZipWrapperIterator(Iterator current, Iterator last) : current(current), last(last) {
|
||||
atEnd = current == last;
|
||||
}
|
||||
|
||||
ZipWrapperIterator operator++() {
|
||||
if (!atEnd) {
|
||||
++current;
|
||||
atEnd = current == last;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type operator*() const {
|
||||
return std::tuple<IteratorValue>(*current);
|
||||
}
|
||||
|
||||
bool operator==(ZipWrapperIterator const& rhs) const {
|
||||
return (atEnd && rhs.atEnd) || (!atEnd && !rhs.atEnd && current == rhs.current && last == rhs.last);
|
||||
}
|
||||
|
||||
bool operator!=(ZipWrapperIterator const& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !atEnd;
|
||||
}
|
||||
|
||||
ZipWrapperIterator begin() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZipWrapperIterator end() const {
|
||||
return ZipWrapperIterator();
|
||||
}
|
||||
};
|
||||
template <typename IteratorT>
|
||||
ZipWrapperIterator<IteratorT> makeZipWrapperIterator(IteratorT current, IteratorT end) {
|
||||
return ZipWrapperIterator<IteratorT>(current, end);
|
||||
}
|
||||
|
||||
// Takes two ZipIterators / ZipTupleIterators and concatenates them into a
|
||||
// single iterator that returns the concatenated tuple.
|
||||
template <typename TailIteratorT, typename HeadIteratorT>
|
||||
class ZipTupleIterator {
|
||||
private:
|
||||
TailIteratorT tailIterator;
|
||||
HeadIteratorT headIterator;
|
||||
bool atEnd;
|
||||
|
||||
public:
|
||||
typedef TailIteratorT TailIterator;
|
||||
typedef HeadIteratorT HeadIterator;
|
||||
|
||||
typedef decltype(*TailIterator()) TailType;
|
||||
typedef decltype(*HeadIterator()) HeadType;
|
||||
|
||||
typedef decltype(std::tuple_cat(std::declval<TailType>(), std::declval<HeadType>())) value_type;
|
||||
|
||||
ZipTupleIterator() : atEnd(true) {}
|
||||
|
||||
ZipTupleIterator(TailIterator tailIterator, HeadIterator headIterator)
|
||||
: tailIterator(tailIterator), headIterator(headIterator) {
|
||||
atEnd = tailIterator == TailIterator() || headIterator == HeadIterator();
|
||||
}
|
||||
|
||||
ZipTupleIterator operator++() {
|
||||
if (!atEnd) {
|
||||
++tailIterator;
|
||||
++headIterator;
|
||||
atEnd = tailIterator == TailIterator() || headIterator == HeadIterator();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type operator*() const {
|
||||
return std::tuple_cat(*tailIterator, *headIterator);
|
||||
}
|
||||
|
||||
bool operator==(ZipTupleIterator const& rhs) const {
|
||||
return (atEnd && rhs.atEnd)
|
||||
|| (!atEnd && !rhs.atEnd && tailIterator == rhs.tailIterator && headIterator == rhs.headIterator);
|
||||
}
|
||||
|
||||
bool operator!=(ZipTupleIterator const& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !atEnd;
|
||||
}
|
||||
|
||||
ZipTupleIterator begin() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
ZipTupleIterator end() const {
|
||||
return ZipTupleIterator();
|
||||
}
|
||||
};
|
||||
template <typename HeadIteratorT, typename TailIteratorT>
|
||||
ZipTupleIterator<HeadIteratorT, TailIteratorT> makeZipTupleIterator(HeadIteratorT head, TailIteratorT tail) {
|
||||
return ZipTupleIterator<HeadIteratorT, TailIteratorT>(head, tail);
|
||||
}
|
||||
|
||||
template <typename Container, typename... Rest>
|
||||
struct zipIteratorReturn {
|
||||
typedef ZipTupleIterator<typename zipIteratorReturn<Container>::type, typename zipIteratorReturn<Rest...>::type> type;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
struct zipIteratorReturn<Container> {
|
||||
typedef ZipWrapperIterator<decltype(std::declval<Container>().begin())> type;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
typename zipIteratorReturn<Container>::type zipIterator(Container& container) {
|
||||
return makeZipWrapperIterator(container.begin(), container.end());
|
||||
}
|
||||
|
||||
template <typename Container, typename... Rest>
|
||||
typename zipIteratorReturn<Container, Rest...>::type zipIterator(Container& container, Rest&... rest) {
|
||||
return makeZipTupleIterator(makeZipWrapperIterator(container.begin(), container.end()), zipIterator(rest...));
|
||||
}
|
||||
|
||||
// END ZIP
|
||||
|
||||
// RANGE
|
||||
|
||||
namespace RangeHelper {
|
||||
|
||||
template <typename Diff>
|
||||
typename std::enable_if<std::is_unsigned<Diff>::value, bool>::type checkIfDiffLessThanZero(Diff) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Diff>
|
||||
typename std::enable_if<!std::is_unsigned<Diff>::value, bool>::type checkIfDiffLessThanZero(Diff diff) {
|
||||
return diff < 0;
|
||||
}
|
||||
}
|
||||
|
||||
STAR_EXCEPTION(RangeException, StarException);
|
||||
|
||||
template <typename Value, typename Diff = int>
|
||||
class RangeIterator : public std::iterator<std::random_access_iterator_tag, Value> {
|
||||
public:
|
||||
RangeIterator() : m_start(), m_end(), m_diff(1), m_current(), m_stop(true) {}
|
||||
|
||||
RangeIterator(Value min, Value max, Diff diff)
|
||||
: m_start(min), m_end(max), m_diff(diff), m_current(min), m_stop(false) {
|
||||
sanity();
|
||||
}
|
||||
|
||||
RangeIterator(Value min, Value max) : m_start(min), m_end(max), m_diff(1), m_current(min), m_stop(false) {
|
||||
sanity();
|
||||
}
|
||||
|
||||
RangeIterator(Value max) : m_start(), m_end(max), m_diff(1), m_current(), m_stop(false) {
|
||||
sanity();
|
||||
}
|
||||
|
||||
RangeIterator(RangeIterator const& rhs) {
|
||||
copy(rhs);
|
||||
}
|
||||
|
||||
RangeIterator& operator=(RangeIterator const& rhs) {
|
||||
copy(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangeIterator& operator+=(Diff steps) {
|
||||
if ((applySteps(m_current, m_diff * steps) >= m_end) != (RangeHelper::checkIfDiffLessThanZero<Diff>(m_diff))) {
|
||||
if (!m_stop) {
|
||||
Diff stepsLeft = stepsBetween(m_current, m_end);
|
||||
m_current = applySteps(m_current, stepsLeft * m_diff);
|
||||
m_stop = true;
|
||||
}
|
||||
} else {
|
||||
m_current = applySteps(m_current, steps * m_diff);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangeIterator operator-=(Diff steps) const {
|
||||
m_stop = false;
|
||||
sanity();
|
||||
|
||||
if (applySteps(m_current, -(m_diff * steps)) < m_start)
|
||||
m_current = m_start;
|
||||
else
|
||||
m_current = applySteps(m_current, -(m_diff * steps));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value operator*() const {
|
||||
return m_current;
|
||||
}
|
||||
|
||||
Value const* operator->() const {
|
||||
return &m_current;
|
||||
}
|
||||
|
||||
Value operator[](unsigned rhs) const {
|
||||
// Should return at maximum, the value that this iterator will normally
|
||||
// reach when at end().
|
||||
rhs = std::min(rhs, stepsBetween(m_start, m_end) + 1);
|
||||
return m_start + rhs * m_diff;
|
||||
}
|
||||
|
||||
RangeIterator& operator++() {
|
||||
return operator+=(1);
|
||||
}
|
||||
|
||||
RangeIterator& operator--() {
|
||||
return operator-=(1);
|
||||
}
|
||||
|
||||
RangeIterator operator++(int) {
|
||||
RangeIterator tmp(*this);
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
RangeIterator operator--(int) {
|
||||
RangeIterator tmp(*this);
|
||||
--this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
RangeIterator operator+(Diff steps) const {
|
||||
RangeIterator copy(*this);
|
||||
copy += steps;
|
||||
return copy;
|
||||
}
|
||||
|
||||
RangeIterator operator-(Diff steps) const {
|
||||
RangeIterator copy(*this);
|
||||
copy -= steps;
|
||||
return copy;
|
||||
}
|
||||
|
||||
int operator-(RangeIterator const& rhs) const {
|
||||
if (!sameClass(rhs))
|
||||
throw RangeException("Attempted to subtract incompatible ranges.");
|
||||
|
||||
return stepsBetween(rhs.m_current, m_current);
|
||||
}
|
||||
|
||||
friend RangeIterator operator+(Diff lhs, RangeIterator const& rhs) {
|
||||
return rhs + lhs;
|
||||
}
|
||||
|
||||
friend RangeIterator operator-(Diff lhs, RangeIterator const& rhs) {
|
||||
return rhs - lhs;
|
||||
}
|
||||
|
||||
bool operator==(RangeIterator const& rhs) const {
|
||||
return (sameClass(rhs) && m_current == rhs.m_current && m_stop == rhs.m_stop);
|
||||
}
|
||||
|
||||
bool operator!=(RangeIterator const& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator<(RangeIterator const& rhs) const {
|
||||
return std::tie(m_start, m_end, m_diff, m_current) < std::tie(rhs.m_start, rhs.m_end, rhs.m_diff, rhs.m_current);
|
||||
}
|
||||
|
||||
bool operator<=(RangeIterator const& rhs) const {
|
||||
return (*this == rhs) || (*this < rhs);
|
||||
}
|
||||
|
||||
bool operator>=(RangeIterator const& rhs) const {
|
||||
return !(*this < rhs);
|
||||
}
|
||||
|
||||
bool operator>(RangeIterator const& rhs) const {
|
||||
return !(*this <= rhs);
|
||||
}
|
||||
|
||||
RangeIterator begin() const {
|
||||
return RangeIterator(m_start, m_end, m_diff);
|
||||
}
|
||||
|
||||
RangeIterator end() const {
|
||||
Diff steps = stepsBetween(m_start, m_end);
|
||||
RangeIterator res(m_start, m_end, m_diff);
|
||||
res += steps;
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
void copy(RangeIterator const& copy) {
|
||||
m_start = copy.m_start;
|
||||
m_end = copy.m_end;
|
||||
m_diff = copy.m_diff;
|
||||
m_current = copy.m_current;
|
||||
m_stop = copy.m_stop;
|
||||
sanity();
|
||||
}
|
||||
|
||||
void sanity() {
|
||||
if (m_diff == 0)
|
||||
throw RangeException("Invalid difference in range function.");
|
||||
|
||||
if ((m_end < m_start) != (RangeHelper::checkIfDiffLessThanZero<Diff>(m_diff))) {
|
||||
if (RangeHelper::checkIfDiffLessThanZero<Diff>(m_diff))
|
||||
throw RangeException("Start cannot be less than end if diff is negative.");
|
||||
throw RangeException("Max cannot be less than min.");
|
||||
}
|
||||
|
||||
if (m_end == m_start)
|
||||
m_stop = true;
|
||||
}
|
||||
|
||||
bool sameClass(RangeIterator const& rhs) const {
|
||||
return m_start == rhs.m_start && m_end == rhs.m_end && m_diff == rhs.m_diff;
|
||||
}
|
||||
|
||||
Diff stepsBetween(Value start, Value end) const {
|
||||
return ((Diff)end - (Diff)start) / m_diff;
|
||||
}
|
||||
|
||||
Value applySteps(Value start, Diff travel) const {
|
||||
return (Value)((Diff)start + travel);
|
||||
}
|
||||
|
||||
Value m_start;
|
||||
Value m_end;
|
||||
Diff m_diff;
|
||||
|
||||
Value m_current;
|
||||
|
||||
bool m_stop;
|
||||
};
|
||||
|
||||
template <typename Numeric, typename Diff>
|
||||
RangeIterator<Numeric, Diff> range(Numeric min, Numeric max, Diff diff) {
|
||||
return RangeIterator<Numeric, Diff>(min, max, diff);
|
||||
}
|
||||
|
||||
template <typename Numeric, typename Diff = int>
|
||||
RangeIterator<Numeric, Diff> range(Numeric max) {
|
||||
return RangeIterator<Numeric, Diff>(max);
|
||||
}
|
||||
|
||||
template <typename Numeric, typename Diff = int>
|
||||
RangeIterator<Numeric, Diff> range(Numeric min, Numeric max) {
|
||||
return RangeIterator<Numeric, Diff>(min, max);
|
||||
}
|
||||
|
||||
template <typename Numeric, typename Diff>
|
||||
RangeIterator<Numeric, Diff> rangeInclusive(Numeric min, Numeric max, Diff diff) {
|
||||
return RangeIterator<Numeric, Diff>(min, (Numeric)((Diff)max + 1), diff);
|
||||
}
|
||||
|
||||
template <typename Numeric, typename Diff = int>
|
||||
RangeIterator<Numeric, Diff> rangeInclusive(Numeric max) {
|
||||
return RangeIterator<Numeric, Diff>((Numeric)((Diff)max + 1));
|
||||
}
|
||||
|
||||
template <typename Numeric, typename Diff = int>
|
||||
RangeIterator<Numeric, Diff> rangeInclusive(Numeric min, Numeric max) {
|
||||
return RangeIterator<Numeric, Diff>(min, (Numeric)((Diff)max + 1));
|
||||
}
|
||||
|
||||
// END RANGE
|
||||
|
||||
// Wraps a forward-iterator to produce {value, index} pairs, similar to
|
||||
// python's enumerate()
|
||||
template <typename Iterator>
|
||||
struct EnumerateIterator {
|
||||
private:
|
||||
Iterator current;
|
||||
Iterator last;
|
||||
size_t index;
|
||||
bool atEnd;
|
||||
|
||||
public:
|
||||
typedef decltype(*std::declval<Iterator>()) IteratorValue;
|
||||
typedef pair<IteratorValue&, size_t> value_type;
|
||||
|
||||
EnumerateIterator() : index(0), atEnd(true) {}
|
||||
|
||||
EnumerateIterator(Iterator begin, Iterator end) : current(begin), last(end), index(0) {
|
||||
atEnd = current == last;
|
||||
}
|
||||
|
||||
EnumerateIterator begin() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
EnumerateIterator end() const {
|
||||
return EnumerateIterator();
|
||||
}
|
||||
|
||||
EnumerateIterator operator++() {
|
||||
if (!atEnd) {
|
||||
++current;
|
||||
++index;
|
||||
|
||||
atEnd = current == last;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
value_type operator*() const {
|
||||
return {*current, index};
|
||||
}
|
||||
|
||||
bool operator==(EnumerateIterator const& rhs) const {
|
||||
return (atEnd && rhs.atEnd) || (!atEnd && !rhs.atEnd && current == rhs.current && last == rhs.last);
|
||||
}
|
||||
|
||||
bool operator!=(EnumerateIterator const& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !atEnd;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterable>
|
||||
EnumerateIterator<decltype(std::declval<Iterable>().begin())> enumerateIterator(Iterable& list) {
|
||||
return EnumerateIterator<decltype(std::declval<Iterable>().begin())>(list.begin(), list.end());
|
||||
}
|
||||
|
||||
template <typename ResultContainer, typename Iterable>
|
||||
ResultContainer enumerateConstruct(Iterable&& list) {
|
||||
ResultContainer res;
|
||||
for (auto el : enumerateIterator(list))
|
||||
res.push_back(move(el));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue