Back to Multi-dimensional array
#ifndef PASTELSYS_SUBARRAY_ITERATOR_H
#define PASTELSYS_SUBARRAY_ITERATOR_H
#include "pastel/sys/subarray.h"
namespace Pastel
{
template <integer N, typename Extent_Expression, typename Stride_Expression>
Vector<integer, N> numbers(
const VectorExpression<integer, N, Extent_Expression>& extent,
const VectorExpression<integer, N, Stride_Expression>& stride)
{
return (extent + abs(stride) - 1) / abs(stride);
}
template <typename Type, integer N>
class SubArray;
template <typename Type, integer N>
class ConstSubArray;
template <typename Type, integer N = 2>
class SubArray_Iterator
: public boost::random_access_iterator_helper<
SubArray_Iterator<Type, N>, Type, integer>
{
public:
friend class SubArray<Type, N>;
Type& operator*() const
{
return *data_;
}
integer n() const
{
return extent_.n();
}
SubArray_Iterator& operator+=(integer amount)
{
PENSURE_OP(index_ + amount, <=, size_);
PENSURE_OP(index_ + amount, >=, 0);
position_ = position(index_ + amount);
data_ = begin_ + dot(stride_, position_);
index_ += amount;
return *this;
}
SubArray_Iterator& operator-=(integer amount)
{
return *this += -amount;
}
integer operator-(const SubArray_Iterator& that) const
{
return index_ - that.index_;
}
SubArray_Iterator& operator++()
{
integer d = n();
for (integer i = 0;i < d;++i)
{
data_ += stride_[i];
index_ += extentStride_[i];
++position_[i];
if (position_[i] >= extent_[i] &&
i != d - 1)
{
data_ -= stride_[i] * position_[i];
index_ -= extentStride_[i] * position_[i];
position_[i] = 0;
}
else
{
break;
}
}
return *this;
}
SubArray_Iterator& operator--()
{
integer d = n();
for (integer i = 0;i < d;++i)
{
data_ -= stride_[i];
index_ -= extentStride_[i];
--position_[i];
if (position_[i] < 0 &&
i != d - 1)
{
data_ += stride_[i] * position_[i];
index_ += extentStride_[i] * position_[i];
position_[i] = extent_[i] - 1;
}
else
{
break;
}
}
return *this;
}
bool operator==(const SubArray_Iterator& that) const
{
return data_ == that.data_;
}
Vector<integer, N> position(
integer index) const
{
PENSURE_OP(index, >=, 0);
PENSURE_OP(index, <=, size());
integer d = n();
Vector<integer, N> result(
ofDimension(d));
for (integer i = d - 1;i > 0;--i)
{
result[i] = index / extentStride_[i];
index -= result[i] * extentStride_[i];
}
result[0] = index;
return result;
}
integer index(
const Vector<integer, N>& position) const
{
PENSURE(allGreaterEqual(position, 0));
PENSURE(allLessEqual(position, extent_));
integer d = n();
integer index = position[0];
for (integer i = 1;i < d;++i)
{
index += extentStride_[i] * position[i];
}
return index;
}
const Vector<integer, N>& position() const
{
return position_;
}
const Vector<integer, N>& extent() const
{
return extent_;
}
const Vector<integer, N>& stride() const
{
return stride_;
}
integer size() const
{
return size_;
}
private:
SubArray_Iterator(
Type* begin,
const Vector<integer, N>& position,
const Vector<integer, N>& extent,
const Vector<integer, N>& stride)
: begin_(begin)
, extent_(extent)
, stride_(stride)
, size_(product(extent))
, extentStride_(extent)
, data_(begin)
, index_(0)
, position_(position)
{
if (size_ > 0)
{
integer d = n();
extentStride_[0] = 1;
for (integer i = 1;i < d;++i)
{
extentStride_[i] =
extentStride_[i - 1] * extent_[i - 1];
}
data_ = begin_ + dot(position, stride);
index_ = index(position);
}
}
// Iteration region
Type* begin_;
Vector<integer, N> extent_;
Vector<integer, N> stride_;
// Precomputed stuff
integer size_;
Vector<integer, N> extentStride_;
// Current position
Type* data_;
integer index_;
Vector<integer, N> position_;
};
template <typename Type, integer N = 2>
class SubArray_ConstIterator
: public boost::random_access_iterator_helper<
SubArray_ConstIterator<Type, N>, const Type, integer>
{
public:
// Using default copy constructor.
// Using default assignment.
// Using default destructor.
friend class SubArray<Type, N>;
friend class ConstSubArray<Type, N>;
SubArray_ConstIterator()
: iter_()
{
}
SubArray_ConstIterator(
const SubArray_Iterator<Type, N>& that)
: iter_(that)
{
}
const Type& operator*() const
{
return *iter_;
}
SubArray_ConstIterator& operator+=(integer amount)
{
iter_ += amount;
return *this;
}
SubArray_ConstIterator& operator-=(integer amount)
{
iter_ -= amount;
return *this;
}
integer operator-(const SubArray_ConstIterator& that) const
{
return iter_ - that.iter_;
}
SubArray_ConstIterator& operator++()
{
++iter_;
return *this;
}
SubArray_ConstIterator& operator--()
{
--iter_;
return *this;
}
const Vector<integer, N>& position() const
{
return iter_.position();
}
const Vector<integer, N>& extent() const
{
return iter_.extent();
}
const Vector<integer, N>& stride() const
{
return iter_.stride();
}
integer size() const
{
return iter_.size();
}
bool operator==(const SubArray_ConstIterator& that) const
{
return iter_ == that.iter_;
}
private:
SubArray_Iterator<Type, N> iter_;
};
}
#endif