36 #ifndef MULTI_HANDLE_HXX
37 #define MULTI_HANDLE_HXX
39 #include "multi_fwd.hxx"
40 #include "metaprogramming.hxx"
41 #include "multi_shape.hxx"
45 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX=Handle::index>
46 struct CoupledHandleCast;
48 #ifndef _MSC_VER // Visual Studio doesn't like these forward declarations
49 template <
unsigned int TARGET_INDEX,
class Handle>
50 typename CoupledHandleCast<TARGET_INDEX, Handle>::reference
53 template <
unsigned int TARGET_INDEX,
class Handle>
54 typename CoupledHandleCast<TARGET_INDEX, Handle>::const_reference
55 get(Handle
const & handle);
65 template <
class T,
class NEXT>
70 typedef NEXT base_type;
71 typedef CoupledHandle<T, NEXT> self_type;
73 static const int index = NEXT::index + 1;
74 static const unsigned int dimensions = NEXT::dimensions;
78 typedef T
const * const_pointer;
79 typedef T & reference;
80 typedef T
const & const_reference;
81 typedef typename base_type::shape_type shape_type;
89 template <
class NEXT1>
90 CoupledHandle(CoupledHandle<T, NEXT1>
const & h, NEXT
const & next)
96 CoupledHandle(const_pointer p, shape_type
const & strides, NEXT
const & next)
98 pointer_(const_cast<pointer>(p)),
102 template <
class Str
ide>
103 CoupledHandle(MultiArrayView<dimensions, T, Stride>
const & v, NEXT
const & next)
105 pointer_(const_cast<pointer>(v.data())),
108 vigra_precondition(v.shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
111 inline void incDim(
int dim)
113 pointer_ += strides_[dim];
114 base_type::incDim(dim);
117 inline void decDim(
int dim)
119 pointer_ -= strides_[dim];
120 base_type::decDim(dim);
125 pointer_ += d*strides_[dim];
126 base_type::addDim(dim, d);
129 inline void add(shape_type
const & d)
131 pointer_ +=
dot(d, strides_);
135 template<
int DIMENSION>
136 inline void increment()
138 pointer_ += strides_[DIMENSION];
139 base_type::template increment<DIMENSION>();
142 template<
int DIMENSION>
143 inline void decrement()
145 pointer_ -= strides_[DIMENSION];
146 base_type::template decrement<DIMENSION>();
150 template<
int DIMENSION>
153 pointer_ += offset*strides_[DIMENSION];
154 base_type::template increment<DIMENSION>(offset);
157 template<
int DIMENSION>
160 pointer_ -= offset*strides_[DIMENSION];
161 base_type::template decrement<DIMENSION>(offset);
164 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
166 pointer_ +=
dot(start, strides_);
167 base_type::restrictToSubarray(start, end);
171 reference operator*()
176 const_reference operator*()
const
186 const_pointer operator->()
const
196 const_pointer ptr()
const
201 shape_type
const & strides()
const
206 MultiArrayView<dimensions, T>
209 return MultiArrayView<dimensions, T>(this->shape(), strides(), ptr() -
dot(this->point(), strides()));
212 template <
unsigned int TARGET_INDEX>
213 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
216 return vigra::get<TARGET_INDEX>(*this);
219 template <
unsigned int TARGET_INDEX>
220 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
223 return vigra::get<TARGET_INDEX>(*this);
236 static const unsigned int index = 0;
237 static const unsigned int dimensions = N;
239 typedef typename MultiArrayShape<N>::type value_type;
240 typedef value_type
const * pointer;
241 typedef value_type
const * const_pointer;
242 typedef value_type
const & reference;
243 typedef value_type
const & const_reference;
244 typedef value_type shape_type;
245 typedef CoupledHandle<value_type, void> self_type;
253 CoupledHandle(value_type
const & shape)
259 CoupledHandle(
typename MultiArrayShape<N+1>::type
const & shape)
261 shape_(shape.begin()),
265 inline void incDim(
int dim)
270 inline void decDim(
int dim)
280 inline void add(shape_type
const & d)
285 template<
int DIMENSION>
286 inline void increment()
291 template<
int DIMENSION>
292 inline void decrement()
298 template<
int DIMENSION>
301 point_[DIMENSION] += offset;
304 template<
int DIMENSION>
307 point_[DIMENSION] -= offset;
310 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
312 point_ = shape_type();
313 shape_ = end - start;
317 inline void incrementIndex()
322 inline void decrementIndex()
329 scanOrderIndex_ += offset;
334 scanOrderIndex_ -= offset;
340 return scanOrderIndex_;
344 const_reference point()
const
350 const_reference shape()
const
355 const_reference operator*()
const
360 const_pointer operator->()
const
365 const_pointer ptr()
const
370 unsigned int borderType()
const
372 return detail::BorderTypeImpl<N>::exec(point_, shape_);
375 template <
unsigned int TARGET_INDEX>
376 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
379 return vigra::get<TARGET_INDEX>(*this);
382 template <
unsigned int TARGET_INDEX>
383 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
386 return vigra::get<TARGET_INDEX>(*this);
389 value_type point_, shape_;
394 template <
class T,
class NEXT>
395 class CoupledHandle<Multiband<T>, NEXT>
399 typedef NEXT base_type;
400 typedef CoupledHandle<Multiband<T>, NEXT> self_type;
402 static const unsigned int index = NEXT::index + 1;
403 static const unsigned int dimensions = NEXT::dimensions;
405 typedef MultiArrayView<1, T, StridedArrayTag> value_type;
406 typedef value_type * pointer;
407 typedef value_type
const * const_pointer;
408 typedef value_type & reference;
409 typedef value_type
const & const_reference;
410 typedef typename base_type::shape_type shape_type;
418 template <
class NEXT1>
419 CoupledHandle(CoupledHandle<Multiband<T>, NEXT1>
const & h, NEXT
const & next)
425 CoupledHandle(const_reference p, shape_type
const & strides, NEXT
const & next)
431 template <
class Str
ide>
432 CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride>
const & v, NEXT
const & next)
434 view_(v.bindInner(shape_type())),
435 strides_(v.bindOuter(0).stride())
437 vigra_precondition(v.bindOuter(0).shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
440 inline void incDim(
int dim)
442 view_.unsafePtr() += strides_[dim];
443 base_type::incDim(dim);
446 inline void decDim(
int dim)
448 view_.unsafePtr() -= strides_[dim];
449 base_type::decDim(dim);
454 view_.unsafePtr() += d*strides_[dim];
455 base_type::addDim(dim, d);
458 inline void add(shape_type
const & d)
460 view_.unsafePtr() +=
dot(d, strides_);
464 template<
int DIMENSION>
465 inline void increment()
467 view_.unsafePtr() += strides_[DIMENSION];
468 base_type::template increment<DIMENSION>();
471 template<
int DIMENSION>
472 inline void decrement()
474 view_.unsafePtr() -= strides_[DIMENSION];
475 base_type::template decrement<DIMENSION>();
479 template<
int DIMENSION>
482 view_.unsafePtr() += offset*strides_[DIMENSION];
483 base_type::template increment<DIMENSION>(offset);
486 template<
int DIMENSION>
489 view_.unsafePtr() -= offset*strides_[DIMENSION];
490 base_type::template decrement<DIMENSION>(offset);
493 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
495 view_.unsafePtr() +=
dot(start, strides_);
496 base_type::restrictToSubarray(start, end);
500 reference operator*()
505 const_reference operator*()
const
515 const_pointer operator->()
const
525 const_pointer ptr()
const
530 shape_type
const & strides()
const
535 MultiArrayView<dimensions+1, Multiband<T> >
538 typedef MultiArrayView<dimensions+1, T> View;
539 typename View::difference_type vshape(SkipInitialization), vstride(SkipInitialization);
540 vshape.template subarray<0, dimensions>() = this->shape();
541 vstride.template subarray<0, dimensions>() = strides();
542 vshape[dimensions] = view_.shape(0);
543 vstride[dimensions] = view_.stride(0);
544 return View(vshape, vstride, view_.data() -
dot(this->point(), strides())).multiband();
547 template <
unsigned int TARGET_INDEX>
548 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
551 return vigra::get<TARGET_INDEX>(*this);
554 template <
unsigned int TARGET_INDEX>
555 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
558 return vigra::get<TARGET_INDEX>(*this);
566 template <
unsigned int N,
class T>
567 class IteratorChunkHandle
570 typedef ChunkedArray<N, T> array_type;
571 typedef typename MultiArrayShape<N>::type shape_type;
573 IteratorChunkHandle()
578 IteratorChunkHandle(shape_type
const & offset)
583 IteratorChunkHandle(IteratorChunkHandle
const & other)
584 : offset_(other.offset_),
588 IteratorChunkHandle & operator=(IteratorChunkHandle
const & other)
590 offset_ = other.offset_;
596 SharedChunkHandle<N, T> * chunk_;
608 template <
class U,
class NEXT>
609 class CoupledHandle<ChunkedMemory<U>, NEXT>
611 public IteratorChunkHandle<NEXT::dimensions, typename UnqualifiedType<U>::type>
614 typedef typename UnqualifiedType<U>::type T;
615 typedef NEXT base_type;
616 typedef IteratorChunkHandle<NEXT::dimensions, T> base_type2;
617 typedef CoupledHandle<ChunkedMemory<U>, NEXT> self_type;
619 static const unsigned int index = NEXT::index + 1;
620 static const unsigned int dimensions = NEXT::dimensions;
622 typedef typename IfBool<UnqualifiedType<U>::isConst,
623 ChunkedArrayBase<dimensions, T>
const,
624 ChunkedArrayBase<dimensions, T> >::type array_type;
625 typedef detail::ChunkShape<dimensions, T> chunk_shape;
626 typedef T value_type;
628 typedef value_type
const * const_pointer;
629 typedef U & reference;
630 typedef value_type
const & const_reference;
631 typedef typename base_type::shape_type shape_type;
642 CoupledHandle(CoupledHandle
const & other)
645 pointer_(other.pointer_),
646 strides_(other.strides_),
647 upper_bound_(other.upper_bound_),
651 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
654 CoupledHandle(array_type
const & array, NEXT
const & next)
658 array_(const_cast<array_type*>(&array))
661 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
668 array_->unrefChunk(
this);
671 CoupledHandle & operator=(CoupledHandle
const & other)
677 array_->unrefChunk(
this);
678 base_type::operator=(other);
679 base_type2::operator=(other);
680 array_ = other.array_;
683 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
687 pointer_ = other.pointer_;
688 strides_ = other.strides_;
689 upper_bound_ = other.upper_bound_;
695 using base_type::point;
696 using base_type::shape;
698 inline void incDim(
int dim)
700 base_type::incDim(dim);
701 pointer_ += strides_[dim];
702 if(point()[dim] == upper_bound_[dim])
705 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
709 inline void decDim(
int dim)
711 base_type::decDim(dim);
712 pointer_ -= strides_[dim];
713 if(point()[dim] < upper_bound_[dim] - array_->chunk_shape_[dim])
716 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
722 base_type::addDim(dim, d);
723 if(point()[dim] < shape()[dim] && point()[dim] >= 0)
724 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
727 inline void add(shape_type
const & d)
730 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
733 template<
int DIMENSION>
734 inline void increment()
737 base_type::template increment<DIMENSION>();
738 pointer_ += strides_[DIMENSION];
739 if(point()[DIMENSION] == upper_bound_[DIMENSION])
741 if(point()[DIMENSION] > shape()[DIMENSION])
744 vigra_invariant(
false,
"CoupledHandle<ChunkedMemory<T>>: internal error.");
746 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
750 template<
int DIMENSION>
751 inline void decrement()
754 base_type::template decrement<DIMENSION>();
755 pointer_ -= strides_[DIMENSION];
756 if(point()[DIMENSION] < upper_bound_[DIMENSION] - array_->chunk_shape_[DIMENSION])
758 if(point()[DIMENSION] < -1)
761 vigra_invariant(
false,
"CoupledHandle<ChunkedMemory<T>>: internal error.");
763 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
767 template<
int DIMENSION>
770 addDim(DIMENSION, d);
773 template<
int DIMENSION>
776 addDim(DIMENSION, -d);
779 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
781 base_type::restrictToSubarray(start, end);
782 this->offset_ += start;
783 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
787 reference operator*()
792 const_reference operator*()
const
802 const_pointer operator->()
const
812 const_pointer ptr()
const
823 template <
unsigned int TARGET_INDEX>
824 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
827 return vigra::get<TARGET_INDEX>(*this);
830 template <
unsigned int TARGET_INDEX>
831 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
834 return vigra::get<TARGET_INDEX>(*this);
838 shape_type strides_, upper_bound_;
843 template <
unsigned TARGET_INDEX>
844 struct Error__CoupledHandle_index_out_of_range;
848 template <
unsigned TARGET_INDEX,
class Handle,
bool isVal
id,
unsigned int INDEX=Handle::index>
849 struct CoupledHandleCastImpl
851 typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type;
852 typedef typename type::value_type value_type;
853 typedef typename type::reference reference;
854 typedef typename type::const_reference const_reference;
857 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX>
858 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX>
860 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type;
861 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> value_type;
862 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> reference;
863 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> const_reference;
866 template <
unsigned TARGET_INDEX,
class Handle>
867 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX>
870 typedef typename type::value_type value_type;
871 typedef typename type::reference reference;
872 typedef typename type::const_reference const_reference;
877 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX>
878 struct CoupledHandleCast
879 :
public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX>
882 template <unsigned int TARGET_INDEX, class Handle>
884 typename CoupledHandleCast<TARGET_INDEX, Handle>::type &
885 cast(Handle & handle)
890 template <unsigned int TARGET_INDEX, class Handle>
892 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const &
893 cast(Handle const & handle)
900 template <unsigned int TARGET_INDEX, class Handle>
902 typename CoupledHandleCast<TARGET_INDEX, Handle>::reference
905 return *cast<TARGET_INDEX>(handle);
910 template <unsigned int TARGET_INDEX, class Handle>
912 typename CoupledHandleCast<TARGET_INDEX, Handle>::const_reference
913 get(Handle const & handle)
915 return *cast<TARGET_INDEX>(handle);
920 template <unsigned int N, class List>
921 struct ComposeCoupledHandle;
923 template <unsigned int N, class T, class TAIL>
924 struct ComposeCoupledHandle<N, TypeList<T, TAIL> >
926 typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType;
927 typedef typename MultiArrayShape<N>::type shape_type;
928 typedef CoupledHandle<T, BaseType> type;
931 type exec(MultiArrayView<N, T, S> const & m,
932 shape_type const & start, shape_type const & end,
933 BaseType const & base)
935 return type(m.subarray(start, end).data(), m.stride(), base);
939 type exec(MultiArrayView<N, T, S> const & m, BaseType const & base)
941 return type(m.data(), m.stride(), base);
945 template <unsigned int N>
946 struct ComposeCoupledHandle<N, void>
948 typedef typename MultiArrayShape<N>::type shape_type;
949 typedef CoupledHandle<shape_type, void> type;
951 type exec(shape_type const & shape)
956 type exec(shape_type const & start, shape_type const & end)
958 return type(end-start);
963 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
964 struct CoupledHandleType
967 typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList;
968 typedef typename ComposeCoupledHandle<N, TypeList>::type type;
971 template <unsigned int N, class T1, class T2, class T3, class T4, class T5>
972 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5>
975 typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList;
976 typedef typename ComposeCoupledHandle<N-1, TypeList>::type type;
980 template <class A, class B>
981 struct ZipCoupledHandles;
983 template <class A, class Head, class Tail>
984 struct ZipCoupledHandles<A, CoupledHandle<Head, Tail> >
986 typedef typename ZipCoupledHandles<A, Tail>::type Next;
987 typedef CoupledHandle<Head, Next> type;
989 static type construct(A const & a, CoupledHandle<Head, Tail> const & h)
991 return type(h, ZipCoupledHandles<A, Tail>::construct(a, (Tail const &)h));
995 template <class A, class Shape>
996 struct ZipCoupledHandles<A, CoupledHandle<Shape, void> >
1000 static type construct(A const & a, CoupledHandle<Shape, void> const &)
1014 template <class Handle, unsigned int INDEX=Handle::index>
1015 struct CoupledHandleTraits
1017 typedef Handle value_type;
1018 typedef Handle & reference;
1019 typedef Handle const & const_reference;
1020 typedef Handle * pointer;
1021 typedef Handle const * const_pointer;
1023 static reference dereference(Handle & h)
1028 static const_reference dereference(Handle const & h)
1034 template <class Handle>
1035 struct CoupledHandleTraits<Handle, 0>
1037 typedef typename Handle::value_type value_type;
1038 typedef typename Handle::reference reference;
1039 typedef typename Handle::const_reference const_reference;
1040 typedef typename Handle::pointer pointer;
1041 typedef typename Handle::const_pointer const_pointer;
1043 static reference dereference(Handle & h)
1048 static const_reference dereference(Handle const & h)
1054 template <class Handle>
1055 struct CoupledHandleTraits<Handle, 1>
1057 typedef typename Handle::value_type value_type;
1058 typedef typename Handle::reference reference;
1059 typedef typename Handle::const_reference const_reference;
1060 typedef typename Handle::pointer pointer;
1061 typedef typename Handle::const_pointer const_pointer;
1063 static reference dereference(Handle & h)
1068 static const_reference dereference(Handle const & h)