36 #ifndef MULTI_ITERATOR_COUPLED_HXX_
37 #define MULTI_ITERATOR_COUPLED_HXX_
39 #include "metaprogramming.hxx"
40 #include "multi_iterator.hxx"
51 template <
unsigned int N,
unsigned int DIMENSION=N-1>
52 struct NeighborhoodTypeImpl
54 typedef typename MultiArrayShape<N>::type shape_type;
56 static unsigned int exec(shape_type
const & point, shape_type
const & shape)
58 unsigned int res = NeighborhoodTypeImpl<N, DIMENSION-1>::exec(point, shape);
59 if(point[DIMENSION] == 0)
60 res |= (1 << 2*DIMENSION);
61 if(point[DIMENSION] == shape[DIMENSION]-1)
62 res |= (2 << 2*DIMENSION);
67 template <
unsigned int N>
68 struct NeighborhoodTypeImpl<N, 0>
70 typedef typename MultiArrayShape<N>::type shape_type;
71 static const unsigned int DIMENSION = 0;
73 static unsigned int exec(shape_type
const & point, shape_type
const & shape)
76 if(point[DIMENSION] == 0)
77 res |= (1 << 2*DIMENSION);
78 if(point[DIMENSION] == shape[DIMENSION]-1)
79 res |= (2 << 2*DIMENSION);
87 template <
class T,
class NEXT>
92 typedef NEXT base_type;
95 static const int index = NEXT::index + 1;
96 static const unsigned int dimensions = NEXT::dimensions;
100 typedef T
const * const_pointer;
101 typedef T & reference;
102 typedef T
const & const_reference;
103 typedef typename base_type::shape_type shape_type;
111 CoupledHandle(const_pointer p, shape_type
const & strides, NEXT
const & next)
113 pointer_(const_cast<pointer>(p)),
117 template <
class Str
ide>
120 pointer_(const_cast<pointer>(v.
data())),
123 vigra_precondition(v.
shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
126 template<
int DIMENSION>
127 inline void increment()
129 pointer_ += strides_[DIMENSION];
130 base_type::template increment<DIMENSION>();
133 template<
int DIMENSION>
134 inline void decrement()
136 pointer_ -= strides_[DIMENSION];
137 base_type::template decrement<DIMENSION>();
141 template<
int DIMENSION>
144 pointer_ += offset*strides_[DIMENSION];
145 base_type::template increment<DIMENSION>(offset);
148 template<
int DIMENSION>
151 pointer_ -= offset*strides_[DIMENSION];
152 base_type::template decrement<DIMENSION>(offset);
155 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
157 pointer_ +=
dot(start, strides_);
158 base_type::restrictToSubarray(start, end);
162 reference operator*()
167 const_reference operator*()
const
177 const_pointer operator->()
const
187 const_pointer ptr()
const
192 shape_type
const & strides()
const
206 static const int index = 0;
207 static const unsigned int dimensions = N;
210 typedef value_type
const * pointer;
211 typedef value_type
const * const_pointer;
212 typedef value_type
const & reference;
213 typedef value_type
const & const_reference;
214 typedef value_type shape_type;
223 CoupledHandle(value_type
const & shape)
229 CoupledHandle(
typename MultiArrayShape<N+1>::type
const & shape)
231 shape_(shape.begin()),
235 template<
int DIMENSION>
236 inline void increment()
241 template<
int DIMENSION>
242 inline void decrement()
248 template<
int DIMENSION>
251 point_[DIMENSION] += offset;
254 template<
int DIMENSION>
257 point_[DIMENSION] -= offset;
260 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
262 point_ = shape_type();
263 shape_ = end - start;
267 inline void incrementIndex()
272 inline void decrementIndex()
279 scanOrderIndex_ += offset;
284 scanOrderIndex_ -= offset;
290 return scanOrderIndex_;
294 const_reference point()
const
300 const_reference shape()
const
305 const_reference operator*()
const
310 const_pointer operator->()
const
315 const_pointer ptr()
const
320 unsigned int neighborhoodType()
const
322 return NeighborhoodTypeImpl<N>::exec(point_, shape_);
325 value_type point_, shape_;
332 template <
unsigned int N,
class T,
class Str
ideTag>
333 class MultiArrayView<N, Multiband<T>, StrideTag>
334 :
public MultiArrayView<N, T, StrideTag>
342 template <
class T,
class NEXT>
343 class CoupledHandle<Multiband<T>, NEXT>
347 typedef NEXT base_type;
348 typedef CoupledHandle<Multiband<T>, NEXT> self_type;
350 static const int index = NEXT::index + 1;
351 static const unsigned int dimensions = NEXT::dimensions;
353 typedef MultiArrayView<1, T, StridedArrayTag> value_type;
354 typedef value_type * pointer;
355 typedef value_type
const * const_pointer;
356 typedef value_type & reference;
357 typedef value_type
const & const_reference;
358 typedef typename base_type::shape_type shape_type;
366 CoupledHandle(const_reference p, shape_type
const & strides, NEXT
const & next)
372 template <
class Str
ide>
373 CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride>
const & v, NEXT
const & next)
375 view_(v.bindInner(shape_type())),
376 strides_(v.bindOuter(0).stride())
378 vigra_precondition(v.bindOuter(0).shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
381 template<
int DIMENSION>
382 inline void increment()
384 view_.unsafePtr() += strides_[DIMENSION];
385 base_type::template increment<DIMENSION>();
388 template<
int DIMENSION>
389 inline void decrement()
391 view_.unsafePtr() -= strides_[DIMENSION];
392 base_type::template decrement<DIMENSION>();
396 template<
int DIMENSION>
399 view_.unsafePtr() += offset*strides_[DIMENSION];
400 base_type::template increment<DIMENSION>(offset);
403 template<
int DIMENSION>
406 view_.unsafePtr() -= offset*strides_[DIMENSION];
407 base_type::template decrement<DIMENSION>(offset);
410 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
412 view_.unsafePtr() +=
dot(start, strides_);
413 base_type::restrictToSubarray(start, end);
417 reference operator*()
422 const_reference operator*()
const
432 const_pointer operator->()
const
442 const_pointer ptr()
const
447 shape_type
const & strides()
const
456 template <
unsigned TARGET_INDEX>
457 struct Error__CoupledHandle_index_out_of_range;
461 template <
unsigned TARGET_INDEX,
class Handle,
bool isVal
id,
unsigned int INDEX=Handle::index>
462 struct CoupledHandleCastImpl
464 typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type;
467 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX>
468 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX>
470 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type;
473 template <
unsigned TARGET_INDEX,
class Handle>
474 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX>
481 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX=Handle::index>
482 struct CoupledHandleCast
483 :
public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX>
486 template <unsigned int TARGET_INDEX, class Handle>
487 typename CoupledHandleCast<TARGET_INDEX, Handle>::type &
488 cast(Handle & handle)
493 template <unsigned int TARGET_INDEX, class Handle>
494 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const &
495 cast(Handle const & handle)
502 template <unsigned int TARGET_INDEX, class Handle>
503 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::reference
506 return *cast<TARGET_INDEX>(handle);
511 template <unsigned int TARGET_INDEX, class Handle>
512 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::const_reference
513 get(Handle const & handle)
515 return *cast<TARGET_INDEX>(handle);
564 template <unsigned int N,
567 class CoupledScanOrderIterator
569 : protected CoupledScanOrderIterator<N, HANDLES, DIMENSION-1>
572 typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type;
573 static const int dimension = DIMENSION;
577 typedef typename MultiArrayShape<dimension+1>::type shape_type;
578 typedef MultiArrayIndex difference_type;
579 typedef CoupledScanOrderIterator iterator;
580 typedef std::random_access_iterator_tag iterator_category;
582 typedef typename base_type::value_type value_type;
587 typedef HANDLES value_type;
590 typedef typename base_type::reference reference;
591 typedef typename base_type::const_reference const_reference;
592 typedef typename base_type::pointer pointer;
594 CoupledScanOrderIterator(value_type const & handles = value_type())
598 value_type operator[](MultiArrayIndex i) const
600 return *(CoupledScanOrderIterator(*this) += i);
603 CoupledScanOrderIterator & operator++()
605 base_type::operator++();
606 if(this->point()[dimension-1] == this->shape()[dimension-1])
609 this->handles_.template increment<dimension>();
614 CoupledScanOrderIterator operator++(
int)
616 CoupledScanOrderIterator res(*
this);
624 shape_type coordOffset;
625 detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), this->shape(), coordOffset);
626 coordOffset -= point();
627 moveRelative(coordOffset);
628 this->handles_.scanOrderIndex_ += i;
632 CoupledScanOrderIterator &
operator+=(
const shape_type &coordOffset)
634 moveRelative(coordOffset);
635 this->handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(this->shape(), coordOffset);
639 CoupledScanOrderIterator & operator--()
641 base_type::operator--();
642 if(this->point()[dimension-1] == -1)
644 base_type::inverseReset();
645 this->handles_.template decrement<dimension>();
650 CoupledScanOrderIterator operator--(
int)
652 CoupledScanOrderIterator res(*
this);
662 CoupledScanOrderIterator &
operator-=(
const shape_type &coordOffset)
681 return CoupledScanOrderIterator(*
this) -= d;
684 CoupledScanOrderIterator
operator+(
const shape_type &coordOffset)
const
686 return CoupledScanOrderIterator(*
this) += coordOffset;
689 CoupledScanOrderIterator
operator-(
const shape_type &coordOffset)
const
691 return CoupledScanOrderIterator(*
this) -= coordOffset;
699 bool operator==(CoupledScanOrderIterator
const & r)
704 bool operator!=(CoupledScanOrderIterator
const & r)
const
709 bool operator<(CoupledScanOrderIterator
const & r)
const
714 bool operator<=(CoupledScanOrderIterator
const & r)
const
719 bool operator>(CoupledScanOrderIterator
const & r)
const
724 bool operator>=(CoupledScanOrderIterator
const & r)
const
729 using base_type::operator*;
730 using base_type::point;
731 using base_type::shape;
732 using base_type::scanOrderIndex;
733 using base_type::atBorder;
734 using base_type::neighborhoodType;
741 template<
unsigned int TARGET_INDEX>
742 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
745 return vigra::get<TARGET_INDEX>(handles_);
750 template<
unsigned int TARGET_INDEX>
751 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
754 return vigra::get<TARGET_INDEX>(handles_);
761 this->handles_.template decrement<dimension>(this->shape()[dimension]);
766 this->handles_.template increment<dimension>(this->shape()[dimension]);
769 void moveRelative(
typename value_type::shape_type
const & coordOffset)
771 base_type::moveRelative(coordOffset);
772 this->handles_.template increment<dimension>(coordOffset[dimension]);
778 template <
unsigned int N,
class HANDLES>
779 class CoupledScanOrderIterator<N, HANDLES, 0>
781 static const int dimension = 0;
785 typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type;
786 typedef HANDLES value_type;
788 typedef value_type & reference;
789 typedef value_type
const & const_reference;
790 typedef value_type * pointer;
791 typedef typename MultiArrayShape<1>::type shape_type;
792 typedef CoupledScanOrderIterator iterator;
793 typedef std::random_access_iterator_tag iterator_category;
795 CoupledScanOrderIterator(value_type
const & handles = value_type())
799 CoupledScanOrderIterator & operator++()
801 handles_.template increment<dimension>();
802 handles_.incrementIndex();
806 CoupledScanOrderIterator operator++(
int)
808 CoupledScanOrderIterator res(*
this);
815 shape_type coordOffset;
816 detail::ScanOrderToCoordinate<N>::exec(i, shape(), coordOffset);
817 moveRelative(coordOffset);
818 handles_.scanOrderIndex_ += i;
822 CoupledScanOrderIterator &
operator+=(
const shape_type &coordOffset)
824 moveRelative(coordOffset);
825 handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(shape(), coordOffset);
829 CoupledScanOrderIterator &
operator-=(
const shape_type &coordOffset)
834 CoupledScanOrderIterator & operator--()
836 handles_.template decrement<dimension>();
837 handles_.decrementIndex();
841 CoupledScanOrderIterator operator--(
int)
843 CoupledScanOrderIterator res(*
this);
855 return *(CoupledScanOrderIterator(*
this) += i);
858 CoupledScanOrderIterator
861 return CoupledScanOrderIterator(*
this) += d;
864 CoupledScanOrderIterator
867 return CoupledScanOrderIterator(*
this) -= d;
870 CoupledScanOrderIterator
operator+(
const shape_type &coordOffset)
const
872 return CoupledScanOrderIterator(*
this) += coordOffset;
875 CoupledScanOrderIterator
operator-(
const shape_type &coordOffset)
const
877 return CoupledScanOrderIterator(*
this) -= coordOffset;
881 operator-(CoupledScanOrderIterator
const & r)
const
883 return scanOrderIndex() - r.scanOrderIndex();
887 operator==(CoupledScanOrderIterator
const & r)
889 return scanOrderIndex() == r.scanOrderIndex();
893 operator!=(CoupledScanOrderIterator
const & r)
const
895 return scanOrderIndex() != r.scanOrderIndex();
899 operator<(CoupledScanOrderIterator
const & r)
const
901 return scanOrderIndex() < r.scanOrderIndex();
905 operator<=(CoupledScanOrderIterator
const & r)
const
907 return scanOrderIndex() <= r.scanOrderIndex();
911 operator>(CoupledScanOrderIterator
const & r)
const
913 return scanOrderIndex() > r.scanOrderIndex();
917 operator>=(CoupledScanOrderIterator
const & r)
const
919 return scanOrderIndex() >= r.scanOrderIndex();
924 return handles_.scanOrderIndex();
927 typename value_type::shape_type
const & point()
const
929 return handles_.point();
932 typename value_type::shape_type
const & shape()
const
934 return handles_.shape();
937 reference operator*()
942 const_reference operator*()
const
947 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
const
950 handles_.restricToSubarray(start, end);
953 CoupledScanOrderIterator getEndIterator()
const
958 bool atBorder()
const
960 return (handles_.neighborhoodType() != 0);
963 unsigned int neighborhoodType()
const
965 return handles_.neighborhoodType();
968 template<
unsigned int TARGET_INDEX>
969 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference
972 return vigra::get<TARGET_INDEX>(handles_);
975 template<
unsigned int TARGET_INDEX>
976 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference
979 return vigra::get<TARGET_INDEX>(handles_);
985 handles_.template decrement<dimension>(shape()[dimension]);
990 handles_.template increment<dimension>(shape()[dimension]);
993 void moveRelative(
typename value_type::shape_type
const & coordOffset)
995 handles_.template increment<dimension>(coordOffset[dimension]);
1002 template <
unsigned int N,
class List>
1003 struct ComposeCoupledHandle;
1005 template <
unsigned int N,
class T,
class TAIL>
1006 struct ComposeCoupledHandle<N, TypeList<T, TAIL> >
1008 typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType;
1009 typedef typename MultiArrayShape<N>::type shape_type;
1010 typedef CoupledHandle<T, BaseType> type;
1013 type exec(MultiArrayView<N, T, S>
const & m,
1014 shape_type
const & start, shape_type
const & end,
1015 BaseType
const & base)
1017 return type(m.subarray(start, end).data(), m.stride(), base);
1021 type exec(MultiArrayView<N, T, S>
const & m, BaseType
const & base)
1023 return type(m.data(), m.stride(), base);
1027 template <
unsigned int N>
1028 struct ComposeCoupledHandle<N, void>
1030 typedef typename MultiArrayShape<N>::type shape_type;
1031 typedef CoupledHandle<shape_type, void> type;
1033 type exec(shape_type
const & shape)
1038 type exec(shape_type
const & start, shape_type
const & end)
1040 return type(end-start);
1044 template <
unsigned int N,
class T1=
void,
class T2=
void,
class T3=
void,
class T4=
void,
class T5=
void>
1045 struct CoupledHandleType
1048 typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList;
1049 typedef typename ComposeCoupledHandle<N, TypeList>::type type;
1052 template <
unsigned int N,
class T1,
class T2,
class T3,
class T4,
class T5>
1053 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5>
1056 typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList;
1057 typedef typename ComposeCoupledHandle<N-1, TypeList>::type type;
1062 template <
unsigned int N,
class T1=
void,
class T2=
void,
class T3=
void,
class T4=
void,
class T5=
void>
1066 typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type
HandleType;
1078 typedef typename CoupledHandleType<N>::type P0;
1081 return IteratorType(P0(shape));
1086 template <
unsigned int N1,
class T1,
class S1>
1087 typename CoupledIteratorType<N1, T1>::type
1090 typedef typename CoupledHandleType<N1, T1>::type P1;
1091 typedef typename P1::base_type P0;
1094 return IteratorType(P1(m1,
1100 template <
unsigned int N1,
class T1,
class S1,
1101 unsigned int N2,
class T2,
class S2>
1102 typename CoupledIteratorType<N1, T1, T2>::type
1106 typedef typename CoupledHandleType<N1, T1, T2>::type P2;
1107 typedef typename P2::base_type P1;
1108 typedef typename P1::base_type P0;
1111 return IteratorType(P2(m2,
1118 template <
unsigned int N1,
class T1,
class S1,
1119 unsigned int N2,
class T2,
class S2,
1120 unsigned int N3,
class T3,
class S3>
1121 typename CoupledIteratorType<N1, T1, T2, T3>::type
1126 typedef typename CoupledHandleType<N1, T1, T2, T3>::type P3;
1127 typedef typename P3::base_type P2;
1128 typedef typename P2::base_type P1;
1129 typedef typename P1::base_type P0;
1132 return IteratorType(P3(m3,
1140 template <
unsigned int N1,
class T1,
class S1,
1141 unsigned int N2,
class T2,
class S2,
1142 unsigned int N3,
class T3,
class S3,
1143 unsigned int N4,
class T4,
class S4>
1144 typename CoupledIteratorType<N1, T1, T2, T3, T4>::type
1150 typedef typename CoupledHandleType<N1, T1, T2, T3, T4>::type P4;
1151 typedef typename P4::base_type P3;
1152 typedef typename P3::base_type P2;
1153 typedef typename P2::base_type P1;
1154 typedef typename P1::base_type P0;
1157 return IteratorType(P4(m4,
1161 P0(m1.shape()))))));
1166 template <
unsigned int N1,
class T1,
class S1,
1167 unsigned int N2,
class T2,
class S2,
1168 unsigned int N3,
class T3,
class S3,
1169 unsigned int N4,
class T4,
class S4,
1170 unsigned int N5,
class T5,
class S5>
1171 typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type
1178 typedef typename CoupledHandleType<N1, T1, T2, T3, T4, T5>::type P5;
1179 typedef typename P5::base_type P4;
1180 typedef typename P4::base_type P3;
1181 typedef typename P3::base_type P2;
1182 typedef typename P2::base_type P1;
1183 typedef typename P1::base_type P0;
1186 return IteratorType(P5(m5,
1191 P0(m1.shape())))))));