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