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);
227 void internal_reset(const_pointer p)
229 pointer_ =
const_cast<pointer
>(p);
242 static const unsigned int index = 0;
243 static const unsigned int dimensions = N;
245 typedef typename MultiArrayShape<N>::type value_type;
246 typedef value_type
const * pointer;
247 typedef value_type
const * const_pointer;
248 typedef value_type
const & reference;
249 typedef value_type
const & const_reference;
250 typedef value_type shape_type;
251 typedef CoupledHandle<value_type, void> self_type;
259 CoupledHandle(value_type
const & shape)
265 CoupledHandle(
typename MultiArrayShape<N+1>::type
const & shape)
267 shape_(shape.begin()),
271 inline void incDim(
int dim)
276 inline void decDim(
int dim)
286 inline void add(shape_type
const & d)
291 template<
int DIMENSION>
292 inline void increment()
297 template<
int DIMENSION>
298 inline void decrement()
304 template<
int DIMENSION>
307 point_[DIMENSION] += offset;
310 template<
int DIMENSION>
313 point_[DIMENSION] -= offset;
316 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
318 point_ = shape_type();
319 shape_ = end - start;
323 inline void incrementIndex()
328 inline void decrementIndex()
335 scanOrderIndex_ += offset;
340 scanOrderIndex_ -= offset;
346 return scanOrderIndex_;
350 const_reference point()
const
356 const_reference shape()
const
361 const_reference operator*()
const
366 const_pointer operator->()
const
371 const_pointer ptr()
const
376 unsigned int borderType()
const
378 return detail::BorderTypeImpl<N>::exec(point_, shape_);
381 template <
unsigned int TARGET_INDEX>
382 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
385 return vigra::get<TARGET_INDEX>(*this);
388 template <
unsigned int TARGET_INDEX>
389 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
392 return vigra::get<TARGET_INDEX>(*this);
396 void internal_reset(value_type
const & point)
401 value_type point_, shape_;
406 template <
class T,
class NEXT>
407 class CoupledHandle<Multiband<T>, NEXT>
411 typedef NEXT base_type;
412 typedef CoupledHandle<Multiband<T>, NEXT> self_type;
414 static const unsigned int index = NEXT::index + 1;
415 static const unsigned int dimensions = NEXT::dimensions;
417 typedef MultiArrayView<1, T, StridedArrayTag> value_type;
418 typedef value_type * pointer;
419 typedef value_type
const * const_pointer;
420 typedef value_type & reference;
421 typedef value_type
const & const_reference;
422 typedef typename base_type::shape_type shape_type;
430 template <
class NEXT1>
431 CoupledHandle(CoupledHandle<Multiband<T>, NEXT1>
const & h, NEXT
const & next)
437 CoupledHandle(const_reference p, shape_type
const & strides, NEXT
const & next)
443 template <
class Str
ide>
444 CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride>
const & v, NEXT
const & next)
446 view_(v.bindInner(shape_type())),
447 strides_(v.bindOuter(0).stride())
449 vigra_precondition(v.bindOuter(0).shape() == this->shape(),
"createCoupledIterator(): shape mismatch.");
452 inline void incDim(
int dim)
454 view_.unsafePtr() += strides_[dim];
455 base_type::incDim(dim);
458 inline void decDim(
int dim)
460 view_.unsafePtr() -= strides_[dim];
461 base_type::decDim(dim);
466 view_.unsafePtr() += d*strides_[dim];
467 base_type::addDim(dim, d);
470 inline void add(shape_type
const & d)
472 view_.unsafePtr() +=
dot(d, strides_);
476 template<
int DIMENSION>
477 inline void increment()
479 view_.unsafePtr() += strides_[DIMENSION];
480 base_type::template increment<DIMENSION>();
483 template<
int DIMENSION>
484 inline void decrement()
486 view_.unsafePtr() -= strides_[DIMENSION];
487 base_type::template decrement<DIMENSION>();
491 template<
int DIMENSION>
494 view_.unsafePtr() += offset*strides_[DIMENSION];
495 base_type::template increment<DIMENSION>(offset);
498 template<
int DIMENSION>
501 view_.unsafePtr() -= offset*strides_[DIMENSION];
502 base_type::template decrement<DIMENSION>(offset);
505 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
507 view_.unsafePtr() +=
dot(start, strides_);
508 base_type::restrictToSubarray(start, end);
512 reference operator*()
517 const_reference operator*()
const
527 const_pointer operator->()
const
537 const_pointer ptr()
const
542 shape_type
const & strides()
const
547 MultiArrayView<dimensions+1, Multiband<T> >
550 typedef MultiArrayView<dimensions+1, T> View;
551 typename View::difference_type vshape(SkipInitialization), vstride(SkipInitialization);
552 vshape.template subarray<0, dimensions>() = this->shape();
553 vstride.template subarray<0, dimensions>() = strides();
554 vshape[dimensions] = view_.shape(0);
555 vstride[dimensions] = view_.stride(0);
556 return View(vshape, vstride, view_.data() -
dot(this->point(), strides())).multiband();
559 template <
unsigned int TARGET_INDEX>
560 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
563 return vigra::get<TARGET_INDEX>(*this);
566 template <
unsigned int TARGET_INDEX>
567 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
570 return vigra::get<TARGET_INDEX>(*this);
574 void internal_reset(U
const &)
576 vigra_fail(
"CoupledHandle<Multiband<T>>::internal_reset(): not implemented.");
584 template <
unsigned int N,
class T>
585 class IteratorChunkHandle
588 typedef ChunkedArray<N, T> array_type;
589 typedef typename MultiArrayShape<N>::type shape_type;
591 IteratorChunkHandle()
596 IteratorChunkHandle(shape_type
const & offset)
601 IteratorChunkHandle(IteratorChunkHandle
const & other)
602 : offset_(other.offset_),
606 IteratorChunkHandle & operator=(IteratorChunkHandle
const & other)
608 offset_ = other.offset_;
614 SharedChunkHandle<N, T> * chunk_;
626 template <
class U,
class NEXT>
627 class CoupledHandle<ChunkedMemory<U>, NEXT>
629 public IteratorChunkHandle<NEXT::dimensions, typename UnqualifiedType<U>::type>
632 typedef typename UnqualifiedType<U>::type T;
633 typedef NEXT base_type;
634 typedef IteratorChunkHandle<NEXT::dimensions, T> base_type2;
635 typedef CoupledHandle<ChunkedMemory<U>, NEXT> self_type;
637 static const unsigned int index = NEXT::index + 1;
638 static const unsigned int dimensions = NEXT::dimensions;
640 typedef typename IfBool<UnqualifiedType<U>::isConst,
641 ChunkedArrayBase<dimensions, T>
const,
642 ChunkedArrayBase<dimensions, T> >::type array_type;
643 typedef detail::ChunkShape<dimensions, T> chunk_shape;
644 typedef T value_type;
646 typedef value_type
const * const_pointer;
647 typedef U & reference;
648 typedef value_type
const & const_reference;
649 typedef typename base_type::shape_type shape_type;
660 CoupledHandle(CoupledHandle
const & other)
663 pointer_(other.pointer_),
664 strides_(other.strides_),
665 upper_bound_(other.upper_bound_),
669 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
672 CoupledHandle(array_type
const & array, NEXT
const & next)
676 array_(const_cast<array_type*>(&array))
679 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
686 array_->unrefChunk(
this);
689 CoupledHandle & operator=(CoupledHandle
const & other)
695 array_->unrefChunk(
this);
696 base_type::operator=(other);
697 base_type2::operator=(other);
698 array_ = other.array_;
701 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
705 pointer_ = other.pointer_;
706 strides_ = other.strides_;
707 upper_bound_ = other.upper_bound_;
713 using base_type::point;
714 using base_type::shape;
716 inline void incDim(
int dim)
718 base_type::incDim(dim);
719 pointer_ += strides_[dim];
720 if(point()[dim] == upper_bound_[dim])
723 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
727 inline void decDim(
int dim)
729 base_type::decDim(dim);
730 pointer_ -= strides_[dim];
731 if(point()[dim] < upper_bound_[dim] - array_->chunk_shape_[dim])
734 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
740 base_type::addDim(dim, d);
741 if(point()[dim] < shape()[dim] && point()[dim] >= 0)
742 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
745 inline void add(shape_type
const & d)
748 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
751 template<
int DIMENSION>
752 inline void increment()
755 base_type::template increment<DIMENSION>();
756 pointer_ += strides_[DIMENSION];
757 if(point()[DIMENSION] == upper_bound_[DIMENSION])
759 if(point()[DIMENSION] > shape()[DIMENSION])
762 vigra_invariant(
false,
"CoupledHandle<ChunkedMemory<T>>: internal error.");
764 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
768 template<
int DIMENSION>
769 inline void decrement()
772 base_type::template decrement<DIMENSION>();
773 pointer_ -= strides_[DIMENSION];
774 if(point()[DIMENSION] < upper_bound_[DIMENSION] - array_->chunk_shape_[DIMENSION])
776 if(point()[DIMENSION] < -1)
779 vigra_invariant(
false,
"CoupledHandle<ChunkedMemory<T>>: internal error.");
781 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
785 template<
int DIMENSION>
788 addDim(DIMENSION, d);
791 template<
int DIMENSION>
794 addDim(DIMENSION, -d);
797 void restrictToSubarray(shape_type
const & start, shape_type
const & end)
799 base_type::restrictToSubarray(start, end);
800 this->offset_ += start;
801 pointer_ = array_->chunkForIterator(point(), strides_, upper_bound_,
this);
805 reference operator*()
810 const_reference operator*()
const
820 const_pointer operator->()
const
830 const_pointer ptr()
const
841 template <
unsigned int TARGET_INDEX>
842 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::reference
845 return vigra::get<TARGET_INDEX>(*this);
848 template <
unsigned int TARGET_INDEX>
849 typename CoupledHandleCast<TARGET_INDEX, CoupledHandle, index>::const_reference
852 return vigra::get<TARGET_INDEX>(*this);
856 void internal_reset(V
const &)
858 vigra_fail(
"CoupledHandle<ChunkedMemory<T>>::internal_reset(): not implemented.");
862 shape_type strides_, upper_bound_;
867 template <
unsigned TARGET_INDEX>
868 struct Error__CoupledHandle_index_out_of_range;
872 template <
unsigned TARGET_INDEX,
class Handle,
bool isVal
id,
unsigned int INDEX=Handle::index>
873 struct CoupledHandleCastImpl
875 typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type;
876 typedef typename type::value_type value_type;
877 typedef typename type::reference reference;
878 typedef typename type::const_reference const_reference;
881 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX>
882 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX>
884 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type;
885 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> value_type;
886 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> reference;
887 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> const_reference;
890 template <
unsigned TARGET_INDEX,
class Handle>
891 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX>
894 typedef typename type::value_type value_type;
895 typedef typename type::reference reference;
896 typedef typename type::const_reference const_reference;
901 template <
unsigned TARGET_INDEX,
class Handle,
unsigned int INDEX>
902 struct CoupledHandleCast
903 :
public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX>
906 template <unsigned int TARGET_INDEX, class Handle>
908 typename CoupledHandleCast<TARGET_INDEX, Handle>::type &
909 cast(Handle & handle)
914 template <unsigned int TARGET_INDEX, class Handle>
916 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const &
917 cast(Handle const & handle)
924 template <unsigned int TARGET_INDEX, class Handle>
926 typename CoupledHandleCast<TARGET_INDEX, Handle>::reference
929 return *cast<TARGET_INDEX>(handle);
934 template <unsigned int TARGET_INDEX, class Handle>
936 typename CoupledHandleCast<TARGET_INDEX, Handle>::const_reference
937 get(Handle const & handle)
939 return *cast<TARGET_INDEX>(handle);
944 template <unsigned int N, class List>
945 struct ComposeCoupledHandle;
947 template <unsigned int N, class T, class TAIL>
948 struct ComposeCoupledHandle<N, TypeList<T, TAIL> >
950 typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType;
951 typedef typename MultiArrayShape<N>::type shape_type;
952 typedef CoupledHandle<T, BaseType> type;
955 type exec(MultiArrayView<N, T, S> const & m,
956 shape_type const & start, shape_type const & end,
957 BaseType const & base)
959 return type(m.subarray(start, end).data(), m.stride(), base);
963 type exec(MultiArrayView<N, T, S> const & m, BaseType const & base)
965 return type(m.data(), m.stride(), base);
969 template <unsigned int N>
970 struct ComposeCoupledHandle<N, void>
972 typedef typename MultiArrayShape<N>::type shape_type;
973 typedef CoupledHandle<shape_type, void> type;
975 type exec(shape_type const & shape)
980 type exec(shape_type const & start, shape_type const & end)
982 return type(end-start);
987 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void>
988 struct CoupledHandleType
991 typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList;
992 typedef typename ComposeCoupledHandle<N, TypeList>::type type;
995 template <unsigned int N, class T1, class T2, class T3, class T4, class T5>
996 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5>
999 typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList;
1000 typedef typename ComposeCoupledHandle<N-1, TypeList>::type type;
1004 template <class A, class B>
1005 struct ZipCoupledHandles;
1007 template <class A, class Head, class Tail>
1008 struct ZipCoupledHandles<A, CoupledHandle<Head, Tail> >
1010 typedef typename ZipCoupledHandles<A, Tail>::type Next;
1011 typedef CoupledHandle<Head, Next> type;
1013 static type construct(A const & a, CoupledHandle<Head, Tail> const & h)
1015 return type(h, ZipCoupledHandles<A, Tail>::construct(a, (Tail const &)h));
1019 template <class A, class Shape>
1020 struct ZipCoupledHandles<A, CoupledHandle<Shape, void> >
1024 static type construct(A const & a, CoupledHandle<Shape, void> const &)
1038 template <class Handle, unsigned int INDEX=Handle::index>
1039 struct CoupledHandleTraits
1041 typedef Handle value_type;
1042 typedef Handle & reference;
1043 typedef Handle const & const_reference;
1044 typedef Handle * pointer;
1045 typedef Handle const * const_pointer;
1047 static reference dereference(Handle & h)
1052 static const_reference dereference(Handle const & h)
1058 template <class Handle>
1059 struct CoupledHandleTraits<Handle, 0>
1061 typedef typename Handle::value_type value_type;
1062 typedef typename Handle::reference reference;
1063 typedef typename Handle::const_reference const_reference;
1064 typedef typename Handle::pointer pointer;
1065 typedef typename Handle::const_pointer const_pointer;
1067 static reference dereference(Handle & h)
1072 static const_reference dereference(Handle const & h)
1078 template <class Handle>
1079 struct CoupledHandleTraits<Handle, 1>
1081 typedef typename Handle::value_type value_type;
1082 typedef typename Handle::reference reference;
1083 typedef typename Handle::const_reference const_reference;
1084 typedef typename Handle::pointer pointer;
1085 typedef typename Handle::const_pointer const_pointer;
1087 static reference dereference(Handle & h)
1092 static const_reference dereference(Handle const & h)
PromoteTraits< V1, V2 >::Promote dot(RGBValue< V1, RIDX1, GIDX1, BIDX1 > const &r1, RGBValue< V2, RIDX2, GIDX2, BIDX2 > const &r2)
dot product
Definition: rgbvalue.hxx:906
void add(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r, FixedPoint< IntBits3, FracBits3 > &result)
addition with enforced result type.
Definition: fixedpoint.hxx:561
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60