Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef TCG_CYCLIC_H
Toshihiro Shimizu 890ddd
#define TCG_CYCLIC_H
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// STD includes
Toshihiro Shimizu 890ddd
#include <iterator></iterator>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// tcg includes
Toshihiro Shimizu 890ddd
#include "numeric_ops.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace tcg
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
//    Cyclic helpers
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace cyclic_ops
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename scalar=""></typename>
Toshihiro Shimizu 890ddd
inline bool ll(Scalar a, Scalar b, Scalar c) { return a <= c ? a < b && b < c : c > b || b > a; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename scalar=""></typename>
Toshihiro Shimizu 890ddd
inline bool lel(Scalar a, Scalar b, Scalar c) { return a <= c ? a <= b && b < c : c > b || b >= a; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename scalar=""></typename>
Toshihiro Shimizu 890ddd
inline bool lle(Scalar a, Scalar b, Scalar c) { return a <= c ? a < b && b <= c : c >= b || b > a; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename scalar=""></typename>
Toshihiro Shimizu 890ddd
inline bool lele(Scalar a, Scalar b, Scalar c) { return a <= c ? a <= b && b <= c : c >= b || b >= a; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef min
Toshihiro Shimizu 890ddd
#undef min
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename scalar=""></typename>
Toshihiro Shimizu 890ddd
Scalar min(Scalar a, Scalar b, Scalar ref)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return lel(ref, a, b) ? a : b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef max
Toshihiro Shimizu 890ddd
#undef max
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename scalar=""></typename>
Toshihiro Shimizu 890ddd
Scalar max(Scalar a, Scalar b, Scalar ref)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return lel(ref, a, b) ? a : b;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename diff_type="" typename="" value_type,=""></typename>
Toshihiro Shimizu 890ddd
value_type increased(const value_type &val, const value_type &start, diff_type length)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return start + numeric_ops::mod(val - start + 1, length);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename diff_type="" typename="" value_type,=""></typename>
Toshihiro Shimizu 890ddd
value_type increased(const value_type &val, const value_type &start, diff_type length, diff_type add)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return start + numeric_ops::mod(val - start + add, length);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename diff_type="" typename="" value_type,=""></typename>
Toshihiro Shimizu 890ddd
value_type decreased(const value_type &val, const value_type &start, diff_type length)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return start + numeric_ops::mod(val - start - 1, length);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename diff_type="" typename="" value_type,=""></typename>
Toshihiro Shimizu 890ddd
value_type decreased(const value_type &val, const value_type &start, diff_type length, diff_type add)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return start + numeric_ops::mod(val - start - add, length);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace cyclic_ops
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
//    Cyclic Iterators
Toshihiro Shimizu 890ddd
//************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename cat="typename" it,="" std::iterator_traits<it="" typename="">::iterator_category></typename>
Toshihiro Shimizu 890ddd
class cyclic_iterator;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename it=""></typename>
Toshihiro Shimizu 890ddd
class cyclic_iterator<it, std::forward_iterator_tag=""></it,>
Toshihiro Shimizu 890ddd
	: public std::iterator
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::value_type,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::difference_type,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::pointer,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::reference></it>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	It m_it, m_begin, m_end;
Toshihiro Shimizu 890ddd
	int m_lap;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	cyclic_iterator() : m_lap(0) {}
Toshihiro Shimizu 890ddd
	cyclic_iterator(const It &it, const It &begin, const It &end, int lap = 0)
Toshihiro Shimizu 890ddd
		: m_it(it), m_begin(begin), m_end(end), m_lap(lap) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator++()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (++m_it == m_end)
Toshihiro Shimizu 890ddd
			++m_lap, m_it = m_begin;
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator++(int)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		operator++();
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::reference operator*() { return *m_it; }
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::pointer operator->() { return m_it.operator->(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool operator==(const cyclic_iterator &it) const { return m_it == it.m_it && m_lap == it.m_lap; }
Toshihiro Shimizu 890ddd
	bool operator!=(const cyclic_iterator &it) const { return !operator==(it); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename it=""></typename>
Toshihiro Shimizu 890ddd
class cyclic_iterator<it, std::bidirectional_iterator_tag=""></it,>
Toshihiro Shimizu 890ddd
	: public std::iterator
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::value_type,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::difference_type,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::pointer,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::reference></it>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	It m_it, m_begin, m_end;
Toshihiro Shimizu 890ddd
	int m_lap;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	cyclic_iterator() : m_lap(0) {}
Toshihiro Shimizu 890ddd
	cyclic_iterator(const It &it, const It &begin, const It &end, int lap = 0)
Toshihiro Shimizu 890ddd
		: m_it(it), m_begin(begin), m_end(end), m_lap(lap) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator++()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (++m_it == m_end)
Toshihiro Shimizu 890ddd
			++m_lap, m_it = m_begin;
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator--()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_it == m_begin)
Toshihiro Shimizu 890ddd
			--m_lap, m_it = m_end;
Toshihiro Shimizu 890ddd
		--m_it;
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator++(int)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		operator++();
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator--(int)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		operator--();
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::reference operator*() { return *m_it; }
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::pointer operator->() { return m_it.operator->(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool operator==(const cyclic_iterator &it) const { return m_it == it.m_it && m_lap == it.m_lap; }
Toshihiro Shimizu 890ddd
	bool operator!=(const cyclic_iterator &it) const { return !operator==(it); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename it=""></typename>
Toshihiro Shimizu 890ddd
class cyclic_iterator<it, std::random_access_iterator_tag=""></it,>
Toshihiro Shimizu 890ddd
	: public std::iterator
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::value_type,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::difference_type,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::pointer,</it>
Toshihiro Shimizu 890ddd
						   typename std::iterator_traits<it>::reference></it>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
protected:
Toshihiro Shimizu 890ddd
	It m_it, m_begin, m_end;
Toshihiro Shimizu 890ddd
	int m_lap;
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::difference_type m_count;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	cyclic_iterator() : m_lap(0), m_count(0) {}
Toshihiro Shimizu 890ddd
	cyclic_iterator(const It &it, const It &begin, const It &end, int lap = 0)
Toshihiro Shimizu 890ddd
		: m_it(it), m_begin(begin), m_end(end), m_lap(lap), m_count(m_end - m_begin) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator++()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (++m_it == m_end)
Toshihiro Shimizu 890ddd
			++m_lap, m_it = m_begin;
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator--()
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		if (m_it == m_begin)
Toshihiro Shimizu 890ddd
			--m_lap, m_it = m_end;
Toshihiro Shimizu 890ddd
		--m_it;
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator++(int)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		operator++();
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator--(int)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		operator--();
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator+=(const typename cyclic_iterator::difference_type &val)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_lap += (val + (m_it - m_begin)) / m_count;
Toshihiro Shimizu 890ddd
		m_it = cyclic_ops::increased(m_it, m_begin, m_count, val);
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator &operator-=(const typename cyclic_iterator::difference_type &val)
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		m_lap -= (val + (m_end - m_it)) / m_count;
Toshihiro Shimizu 890ddd
		m_it = cyclic_ops::decreased(m_it, m_begin, m_count, val);
Toshihiro Shimizu 890ddd
		return *this;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::difference_type operator-(const cyclic_iterator &it) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		assert(m_begin == it.m_begin && m_end == it.m_end);
Toshihiro Shimizu 890ddd
		return m_it - it.m_it + m_lap * m_count - it.m_lap * it.m_count;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator+(const typename cyclic_iterator::difference_type &val) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		it += val;
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	cyclic_iterator operator-(const typename cyclic_iterator::difference_type &val) const
Toshihiro Shimizu 890ddd
	{
Toshihiro Shimizu 890ddd
		cyclic_iterator it(*this);
Toshihiro Shimizu 890ddd
		it -= val;
Toshihiro Shimizu 890ddd
		return it;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::reference operator*() const { return *m_it; }
Toshihiro Shimizu 890ddd
	typename cyclic_iterator::pointer operator->() const { return m_it.operator->(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool operator==(const cyclic_iterator &it) const { return m_it == it.m_it && m_lap == it.m_lap; }
Toshihiro Shimizu 890ddd
	bool operator!=(const cyclic_iterator &it) const { return !operator==(it); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool operator<(const cyclic_iterator &it) const { return m_lap < it.m_lap || m_it < it.m_it; }
Toshihiro Shimizu 890ddd
	bool operator>(const cyclic_iterator &it) const { return m_lap > it.m_lap || m_it > it.m_it; }
Toshihiro Shimizu 890ddd
	bool operator<=(const cyclic_iterator &it) const { return m_lap <= it.m_lap || m_it <= it.m_it; }
Toshihiro Shimizu 890ddd
	bool operator>=(const cyclic_iterator &it) const { return m_lap >= it.m_lap || m_it >= it.m_it; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
} //namespace tcg
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif //TCG_CYCLIC_H