36 #ifndef MULTI_ITERATOR_COUPLED_HXX
37 #define MULTI_ITERATOR_COUPLED_HXX
39 #include "metaprogramming.hxx"
40 #include "multi_shape.hxx"
51 template <
class T,
class NEXT>
56 typedef NEXT base_type;
59 static const int index = NEXT::index + 1;
60 static const unsigned int dimensions = NEXT::dimensions;
64 typedef T
const * const_pointer;
65 typedef T & reference;
66 typedef T
const & const_reference;
67 typedef typename base_type::shape_type shape_type;
75 CoupledHandle(const_pointer p, shape_type
const & strides, NEXT
const & next)
77 pointer_(const_cast<pointer>(p)),
81 template <
class Str
ide>
84 pointer_(const_cast<pointer>(v.
data())),
87 vigra_precondition(v.
shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
90 template<
int DIMENSION>
91 inline void increment()
93 pointer_ += strides_[DIMENSION];
94 base_type::template increment<DIMENSION>();
97 template<
int DIMENSION>
98 inline void decrement()
100 pointer_ -= strides_[DIMENSION];
101 base_type::template decrement<DIMENSION>();
105 template<
int DIMENSION>
108 pointer_ += offset*strides_[DIMENSION];
109 base_type::template increment<DIMENSION>(offset);
112 template<
int DIMENSION>
115 pointer_ -= offset*strides_[DIMENSION];
116 base_type::template decrement<DIMENSION>(offset);
119 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
121 pointer_ +=
dot(start, strides_);
122 base_type::restrictToSubarray(start, end);
126 reference operator*()
131 const_reference operator*()
const
141 const_pointer operator->()
const
151 const_pointer ptr()
const
156 shape_type
const & strides()
const
170 static const int index = 0;
171 static const unsigned int dimensions = N;
174 typedef value_type
const * pointer;
175 typedef value_type
const * const_pointer;
176 typedef value_type
const & reference;
177 typedef value_type
const & const_reference;
178 typedef value_type shape_type;
187 CoupledHandle(value_type
const & shape)
193 CoupledHandle(
typename MultiArrayShape<N+1>::type
const & shape)
195 shape_(shape.begin()),
199 template<
int DIMENSION>
200 inline void increment()
205 template<
int DIMENSION>
206 inline void decrement()
212 template<
int DIMENSION>
215 point_[DIMENSION] += offset;
218 template<
int DIMENSION>
221 point_[DIMENSION] -= offset;
224 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
226 point_ = shape_type();
227 shape_ = end - start;
231 inline void incrementIndex()
236 inline void decrementIndex()
243 scanOrderIndex_ += offset;
248 scanOrderIndex_ -= offset;
254 return scanOrderIndex_;
258 const_reference point()
const
264 const_reference shape()
const
269 const_reference operator*()
const
274 const_pointer operator->()
const
279 const_pointer ptr()
const
284 unsigned int borderType()
const
286 return detail::BorderTypeImpl<N>::exec(point_, shape_);
289 value_type point_, shape_;
293 template <
unsigned int N,
class T,
class Str
ideTag>
294 class MultiArrayView<N, Multiband<T>, StrideTag>
295 :
public MultiArrayView<N, T, StrideTag>
303 template <
class T,
class NEXT>
304 class CoupledHandle<Multiband<T>, NEXT>
308 typedef NEXT base_type;
309 typedef CoupledHandle<Multiband<T>, NEXT> self_type;
311 static const int index = NEXT::index + 1;
312 static const unsigned int dimensions = NEXT::dimensions;
314 typedef MultiArrayView<1, T, StridedArrayTag> value_type;
315 typedef value_type * pointer;
316 typedef value_type
const * const_pointer;
317 typedef value_type & reference;
318 typedef value_type
const & const_reference;
319 typedef typename base_type::shape_type shape_type;
327 CoupledHandle(const_reference p, shape_type
const & strides, NEXT
const & next)
333 template <
class Str
ide>
334 CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride>
const & v, NEXT
const & next)
336 view_(v.bindInner(shape_type())),
337 strides_(v.bindOuter(0).stride())
339 vigra_precondition(v.bindOuter(0).shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
342 template<
int DIMENSION>
343 inline void increment()
345 view_.unsafePtr() += strides_[DIMENSION];
346 base_type::template increment<DIMENSION>();
349 template<
int DIMENSION>
350 inline void decrement()
352 view_.unsafePtr() -= strides_[DIMENSION];
353 base_type::template decrement<DIMENSION>();
357 template<
int DIMENSION>
360 view_.unsafePtr() += offset*strides_[DIMENSION];
361 base_type::template increment<DIMENSION>(offset);
364 template<
int DIMENSION>
367 view_.unsafePtr() -= offset*strides_[DIMENSION];
368 base_type::template decrement<DIMENSION>(offset);
371 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
373 view_.unsafePtr() +=
dot(start, strides_);
374 base_type::restrictToSubarray(start, end);
378 reference operator*()
383 const_reference operator*()
const
393 const_pointer operator->()
const
403 const_pointer ptr()
const
408 shape_type
const & strides()
const
417 template <
unsigned TARGET_INDEX>
418 struct Error__CoupledHandle_index_out_of_range;
422 template <
unsigned TARGET_INDEX,
class Handle,
bool isVal
id,
unsigned int INDEX=Handle::index>
423 struct CoupledHandleCastImpl
425 typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type;
428 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX>
429 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX>
431 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type;
434 template <
unsigned TARGET_INDEX,
class Handle>
435 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX>
442 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX=Handle::index>
443 struct CoupledHandleCast
444 :
public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX>
447 template <unsigned int TARGET_INDEX, class Handle>
448 typename CoupledHandleCast<TARGET_INDEX, Handle>::type &
449 cast(Handle & handle)
454 template <unsigned int TARGET_INDEX, class Handle>
455 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const &
456 cast(Handle const & handle)
463 template <unsigned int TARGET_INDEX, class Handle>
464 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::reference
467 return *cast<TARGET_INDEX>(handle);
472 template <unsigned int TARGET_INDEX, class Handle>
473 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::const_reference
474 get(Handle const & handle)
476 return *cast<TARGET_INDEX>(handle);
523 template <unsigned int N,
524 class HANDLES=CoupledHandle<TinyVector<MultiArrayIndex, N>, void>,
526 class CoupledScanOrderIterator
528 : protected CoupledScanOrderIterator<N, HANDLES, DIMENSION-1>
531 typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type;
532 static const int dimension = DIMENSION;
536 typedef typename MultiArrayShape<dimension+1>::type shape_type;
537 typedef MultiArrayIndex difference_type;
538 typedef CoupledScanOrderIterator iterator;
539 typedef std::random_access_iterator_tag iterator_category;
541 typedef typename base_type::value_type value_type;
546 typedef HANDLES value_type;
549 typedef typename base_type::reference reference;
550 typedef typename base_type::const_reference const_reference;
551 typedef typename base_type::pointer pointer;
553 explicit CoupledScanOrderIterator(value_type const & handles = value_type())
557 value_type operator[](MultiArrayIndex i) const
559 return *(CoupledScanOrderIterator(*this) += i);
562 CoupledScanOrderIterator & operator++()
564 base_type::operator++();
565 if(this->point()[dimension-1] == this->shape()[dimension-1])
568 this->handles_.template increment<dimension>();
573 CoupledScanOrderIterator operator++(
int)
575 CoupledScanOrderIterator res(*
this);
583 shape_type coordOffset;
584 detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), this->shape(), coordOffset);
585 coordOffset -= point();
586 moveRelative(coordOffset);
587 this->handles_.scanOrderIndex_ += i;
591 CoupledScanOrderIterator &
operator+=(
const shape_type &coordOffset)
593 moveRelative(coordOffset);
594 this->handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(this->shape(), coordOffset);
598 CoupledScanOrderIterator & operator--()
600 base_type::operator--();
601 if(this->point()[dimension-1] == -1)
603 base_type::inverseReset();
604 this->handles_.template decrement<dimension>();
609 CoupledScanOrderIterator operator--(
int)
611 CoupledScanOrderIterator res(*
this);
621 CoupledScanOrderIterator &
operator-=(
const shape_type &coordOffset)
630 return operator+(
prod(this->shape()) - this->scanOrderIndex());
640 return CoupledScanOrderIterator(*
this) -= d;
643 CoupledScanOrderIterator
operator+(
const shape_type &coordOffset)
const
645 return CoupledScanOrderIterator(*
this) += coordOffset;
648 CoupledScanOrderIterator
operator-(
const shape_type &coordOffset)
const
650 return CoupledScanOrderIterator(*
this) -= coordOffset;
658 bool operator==(CoupledScanOrderIterator
const & r)
const
663 bool operator!=(CoupledScanOrderIterator
const & r)
const
668 bool operator<(CoupledScanOrderIterator
const & r)
const
673 bool operator<=(CoupledScanOrderIterator
const & r)
const
678 bool operator>(CoupledScanOrderIterator
const & r)
const
683 bool operator>=(CoupledScanOrderIterator
const & r)
const
688 CoupledScanOrderIterator & restrictToSubarray(shape_type
const & start, shape_type
const & end)
691 this->handles_.restrictToSubarray(start, end);
695 using base_type::operator*;
696 using base_type::point;
697 using base_type::shape;
698 using base_type::scanOrderIndex;
699 using base_type::atBorder;
700 using base_type::borderType;
702 using base_type::isValid;
703 using base_type::atEnd;
709 template<
unsigned int TARGET_INDEX>
710 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
715 template<
unsigned int TARGET_INDEX>
716 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
724 this->handles_.template decrement<dimension>(this->shape()[dimension]);
729 this->handles_.template increment<dimension>(this->shape()[dimension]);
732 void moveRelative(
typename value_type::shape_type
const & coordOffset)
734 base_type::moveRelative(coordOffset);
735 this->handles_.template increment<dimension>(coordOffset[dimension]);
741 template <
unsigned int N,
class HANDLES>
742 class CoupledScanOrderIterator<N, HANDLES, 0>
744 static const int dimension = 0;
748 typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type;
749 typedef HANDLES value_type;
751 typedef value_type & reference;
752 typedef value_type
const & const_reference;
753 typedef value_type * pointer;
754 typedef typename MultiArrayShape<1>::type shape_type;
755 typedef CoupledScanOrderIterator iterator;
756 typedef std::random_access_iterator_tag iterator_category;
758 explicit CoupledScanOrderIterator(value_type
const & handles = value_type())
762 CoupledScanOrderIterator & operator++()
764 handles_.template increment<dimension>();
765 handles_.incrementIndex();
769 CoupledScanOrderIterator operator++(
int)
771 CoupledScanOrderIterator res(*
this);
778 shape_type coordOffset;
779 detail::ScanOrderToCoordinate<N>::exec(i, shape(), coordOffset);
780 moveRelative(coordOffset);
781 handles_.scanOrderIndex_ += i;
785 CoupledScanOrderIterator &
operator+=(
const shape_type &coordOffset)
787 moveRelative(coordOffset);
788 handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(shape(), coordOffset);
792 CoupledScanOrderIterator &
operator-=(
const shape_type &coordOffset)
797 CoupledScanOrderIterator & operator--()
799 handles_.template decrement<dimension>();
800 handles_.decrementIndex();
804 CoupledScanOrderIterator operator--(
int)
806 CoupledScanOrderIterator res(*
this);
818 return *(CoupledScanOrderIterator(*
this) += i);
821 CoupledScanOrderIterator
824 return CoupledScanOrderIterator(*
this) += d;
827 CoupledScanOrderIterator
830 return CoupledScanOrderIterator(*
this) -= d;
833 CoupledScanOrderIterator
operator+(
const shape_type &coordOffset)
const
835 return CoupledScanOrderIterator(*
this) += coordOffset;
838 CoupledScanOrderIterator
operator-(
const shape_type &coordOffset)
const
840 return CoupledScanOrderIterator(*
this) -= coordOffset;
844 operator-(CoupledScanOrderIterator
const & r)
const
846 return scanOrderIndex() - r.scanOrderIndex();
849 bool operator==(CoupledScanOrderIterator
const & r)
const
851 return scanOrderIndex() == r.scanOrderIndex();
854 bool operator!=(CoupledScanOrderIterator
const & r)
const
856 return scanOrderIndex() != r.scanOrderIndex();
859 bool operator<(CoupledScanOrderIterator
const & r)
const
861 return scanOrderIndex() < r.scanOrderIndex();
864 bool operator<=(CoupledScanOrderIterator
const & r)
const
866 return scanOrderIndex() <= r.scanOrderIndex();
869 bool operator>(CoupledScanOrderIterator
const & r)
const
871 return scanOrderIndex() > r.scanOrderIndex();
874 bool operator>=(CoupledScanOrderIterator
const & r)
const
876 return scanOrderIndex() >= r.scanOrderIndex();
881 return handles_.scanOrderIndex() <
prod(shape());
886 return handles_.scanOrderIndex() >=
prod(shape());
891 return handles_.scanOrderIndex();
894 typename value_type::shape_type
const & point()
const
896 return handles_.point();
899 typename value_type::shape_type
const & shape()
const
901 return handles_.shape();
904 reference operator*()
909 const_reference operator*()
const
914 CoupledScanOrderIterator & restrictToSubarray(shape_type
const & start, shape_type
const & end)
917 handles_.restrictToSubarray(start, end);
921 CoupledScanOrderIterator getEndIterator()
const
926 bool atBorder()
const
928 return (handles_.borderType() != 0);
931 unsigned int borderType()
const
933 return handles_.borderType();
936 template<
unsigned int TARGET_INDEX>
937 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
940 return vigra::get<TARGET_INDEX>(handles_);
943 template<
unsigned int TARGET_INDEX>
944 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
947 return vigra::get<TARGET_INDEX>(handles_);
953 handles_.template decrement<dimension>(shape()[dimension]);
958 handles_.template increment<dimension>(shape()[dimension]);
961 void moveRelative(
typename value_type::shape_type
const & coordOffset)
963 handles_.template increment<dimension>(coordOffset[dimension]);
970 template <
unsigned int N,
class List>
971 struct ComposeCoupledHandle;
973 template <
unsigned int N,
class T,
class TAIL>
974 struct ComposeCoupledHandle<N, TypeList<T, TAIL> >
976 typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType;
977 typedef typename MultiArrayShape<N>::type shape_type;
978 typedef CoupledHandle<T, BaseType> type;
981 type exec(MultiArrayView<N, T, S>
const & m,
982 shape_type
const & start, shape_type
const & end,
983 BaseType
const & base)
985 return type(m.subarray(start, end).data(), m.stride(), base);
989 type exec(MultiArrayView<N, T, S>
const & m, BaseType
const & base)
991 return type(m.data(), m.stride(), base);
995 template <
unsigned int N>
996 struct ComposeCoupledHandle<N, void>
998 typedef typename MultiArrayShape<N>::type shape_type;
999 typedef CoupledHandle<shape_type, void> type;
1001 type exec(shape_type
const & shape)
1006 type exec(shape_type
const & start, shape_type
const & end)
1008 return type(end-start);
1012 template <
unsigned int N,
class T1=
void,
class T2=
void,
class T3=
void,
class T4=
void,
class T5=
void>
1013 struct CoupledHandleType
1016 typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList;
1017 typedef typename ComposeCoupledHandle<N, TypeList>::type type;
1020 template <
unsigned int N,
class T1,
class T2,
class T3,
class T4,
class T5>
1021 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5>
1024 typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList;
1025 typedef typename ComposeCoupledHandle<N-1, TypeList>::type type;
1030 template <
unsigned int N,
class T1=
void,
class T2=
void,
class T3=
void,
class T4=
void,
class T5=
void>
1034 typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type
HandleType;
1043 template <
unsigned int N,
class T1=
void,
class T2=
void,
class T3=
void,
class T4=
void,
class T5=
void>
1054 typedef typename CoupledHandleType<N>::type P0;
1057 return IteratorType(P0(shape));
1062 template <
unsigned int N1,
class T1,
class S1>
1063 typename CoupledIteratorType<N1, T1>::type
1066 typedef typename CoupledHandleType<N1, T1>::type P1;
1067 typedef typename P1::base_type P0;
1070 return IteratorType(P1(m1,
1076 template <
unsigned int N1,
class T1,
class S1,
1077 unsigned int N2,
class T2,
class S2>
1078 typename CoupledIteratorType<N1, T1, T2>::type
1082 typedef typename CoupledHandleType<N1, T1, T2>::type P2;
1083 typedef typename P2::base_type P1;
1084 typedef typename P1::base_type P0;
1087 return IteratorType(P2(m2,
1094 template <
unsigned int N1,
class T1,
class S1,
1095 unsigned int N2,
class T2,
class S2,
1096 unsigned int N3,
class T3,
class S3>
1097 typename CoupledIteratorType<N1, T1, T2, T3>::type
1102 typedef typename CoupledHandleType<N1, T1, T2, T3>::type P3;
1103 typedef typename P3::base_type P2;
1104 typedef typename P2::base_type P1;
1105 typedef typename P1::base_type P0;
1108 return IteratorType(P3(m3,
1116 template <
unsigned int N1,
class T1,
class S1,
1117 unsigned int N2,
class T2,
class S2,
1118 unsigned int N3,
class T3,
class S3,
1119 unsigned int N4,
class T4,
class S4>
1120 typename CoupledIteratorType<N1, T1, T2, T3, T4>::type
1126 typedef typename CoupledHandleType<N1, T1, T2, T3, T4>::type P4;
1127 typedef typename P4::base_type P3;
1128 typedef typename P3::base_type P2;
1129 typedef typename P2::base_type P1;
1130 typedef typename P1::base_type P0;
1133 return IteratorType(P4(m4,
1137 P0(m1.shape()))))));
1142 template <
unsigned int N1,
class T1,
class S1,
1143 unsigned int N2,
class T2,
class S2,
1144 unsigned int N3,
class T3,
class S3,
1145 unsigned int N4,
class T4,
class S4,
1146 unsigned int N5,
class T5,
class S5>
1147 typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type
1154 typedef typename CoupledHandleType<N1, T1, T2, T3, T4, T5>::type P5;
1155 typedef typename P5::base_type P4;
1156 typedef typename P4::base_type P3;
1157 typedef typename P3::base_type P2;
1158 typedef typename P2::base_type P1;
1159 typedef typename P1::base_type P0;
1162 return IteratorType(P5(m5,
1167 P0(m1.shape())))))));
1176 template <
unsigned int N,
class HANDLES,
int DIMENSION>
1177 ostream & operator<<(ostream & o, vigra::CoupledScanOrderIterator<N, HANDLES, DIMENSION>
const & i)