37 #ifndef VIGRA_MULTI_ARRAY_HXX
38 #define VIGRA_MULTI_ARRAY_HXX
42 #include "accessor.hxx"
43 #include "tinyvector.hxx"
44 #include "rgbvalue.hxx"
45 #include "basicimageview.hxx"
46 #include "imageiterator.hxx"
47 #include "numerictraits.hxx"
48 #include "multi_iterator.hxx"
49 #include "metaprogramming.hxx"
50 #include "mathutil.hxx"
53 #ifdef VIGRA_CHECK_BOUNDS
54 #define VIGRA_ASSERT_INSIDE(diff) \
55 vigra_precondition(this->isInside(diff), "Index out of bounds")
57 #define VIGRA_ASSERT_INSIDE(diff)
75 template <
unsigned int N>
76 inline TinyVector <MultiArrayIndex, N>
77 defaultStride(
const TinyVector <MultiArrayIndex, N> &shape)
79 TinyVector <MultiArrayIndex, N> ret;
81 for (
int i = 1; i < (int)N; ++i)
82 ret [i] = ret [i-1] * shape [i-1];
99 struct ScanOrderToOffset
104 const TinyVector <MultiArrayIndex, N> & stride)
106 return stride[N-K] * (d % shape[N-K]) +
107 ScanOrderToOffset<K-1>::exec(d / shape[N-K], shape, stride);
112 struct ScanOrderToOffset<1>
117 const TinyVector <MultiArrayIndex, N> & stride)
119 return stride[N-1] * d;
124 struct ScanOrderToCoordinate
129 TinyVector <MultiArrayIndex, N> & result)
131 result[N-K] = (d % shape[N-K]);
132 ScanOrderToCoordinate<K-1>::exec(d / shape[N-K], shape, result);
137 struct ScanOrderToCoordinate<1>
142 TinyVector <MultiArrayIndex, N> & result)
150 struct CoordinatesToOffest
154 exec(
const TinyVector <MultiArrayIndex, N> & stride,
MultiArrayIndex x)
156 return stride[0] * x;
162 return stride[0] * x + stride[1] * y;
167 struct CoordinatesToOffest<UnstridedArrayTag>
179 return x + stride[1] * y;
198 template <
class Str
ideTag,
unsigned int N>
201 typedef StrideTag type;
204 template <
class Str
ideTag>
205 struct MaybeStrided <StrideTag, 0>
207 typedef StridedArrayTag type;
225 struct MultiIteratorChooser
229 template <
unsigned int N,
class T,
class REFERENCE,
class POINTER>
250 struct MultiIteratorChooser <StridedArrayTag>
252 template <
unsigned int N,
class T,
class REFERENCE,
class POINTER>
255 typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type;
273 struct MultiIteratorChooser <UnstridedArrayTag>
275 template <
unsigned int N,
class T,
class REFERENCE,
class POINTER>
278 typedef MultiIterator <N, T, REFERENCE, POINTER> type;
288 template <
class DestIterator,
class Shape,
class T>
290 initMultiArrayData(DestIterator d, Shape
const & shape, T
const & init, MetaInt<0>)
292 DestIterator dend = d + shape[0];
299 template <
class DestIterator,
class Shape,
class T,
int N>
301 initMultiArrayData(DestIterator d, Shape
const & shape, T
const & init, MetaInt<N>)
303 DestIterator dend = d + shape[N];
306 initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
311 #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \
312 template <class SrcIterator, class Shape, class DestIterator> \
314 name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<0>) \
316 SrcIterator send = s + shape[0]; \
317 for(; s < send; ++s, ++d) \
319 *d op detail::RequiresExplicitCast<typename DestIterator::value_type>::cast(*s); \
323 template <class Ref, class Ptr, class Shape, class DestIterator> \
325 name##MultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & shape, DestIterator d, MetaInt<0>) \
327 Ptr s = &(*si), send = s + shape[0]; \
328 for(; s < send; ++s, ++d) \
330 *d op detail::RequiresExplicitCast<typename DestIterator::value_type>::cast(*s); \
334 template <class SrcIterator, class Shape, class DestIterator, int N> \
336 name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<N>) \
338 SrcIterator send = s + shape[N]; \
339 for(; s < send; ++s, ++d) \
341 name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>()); \
345 template <class DestIterator, class Shape, class T> \
347 name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<0>) \
349 DestIterator dend = d + shape[0]; \
350 for(; d < dend; ++d) \
352 *d op detail::RequiresExplicitCast<typename DestIterator::value_type>::cast(init); \
356 template <class DestIterator, class Shape, class T, int N> \
358 name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<N>) \
360 DestIterator dend = d + shape[N]; \
361 for(; d < dend; ++d) \
363 name##ScalarMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); \
367 VIGRA_COPY_MULTI_ARRAY_DATA(copy, =)
368 VIGRA_COPY_MULTI_ARRAY_DATA(copyAdd, +=)
369 VIGRA_COPY_MULTI_ARRAY_DATA(copySub, -=)
370 VIGRA_COPY_MULTI_ARRAY_DATA(copyMul, *=)
371 VIGRA_COPY_MULTI_ARRAY_DATA(copyDiv, /=)
373 #undef VIGRA_COPY_MULTI_ARRAY_DATA
375 template <
class SrcIterator,
class Shape,
class T,
class ALLOC>
377 uninitializedCopyMultiArrayData(SrcIterator s, Shape
const & shape, T * & d, ALLOC & a, MetaInt<0>)
379 SrcIterator send = s + shape[0];
380 for(; s < send; ++s, ++d)
382 a.construct(d, static_cast<T const &>(*s));
387 template <
class Ref,
class Ptr,
class Shape,
class T,
class ALLOC>
389 uninitializedCopyMultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape
const & shape, T * & d, ALLOC & a, MetaInt<0>)
391 Ptr s = &(*si), send = s + shape[0];
392 for(; s < send; ++s, ++d)
394 a.construct(d, static_cast<T const &>(*s));
398 template <
class SrcIterator,
class Shape,
class T,
class ALLOC,
int N>
400 uninitializedCopyMultiArrayData(SrcIterator s, Shape
const & shape, T * & d, ALLOC & a, MetaInt<N>)
402 SrcIterator send = s + shape[N];
405 uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1>());
409 template <
class SrcIterator,
class Shape,
class T,
class Functor>
411 reduceOverMultiArray(SrcIterator s, Shape
const & shape, T & result, Functor
const & f, MetaInt<0>)
413 SrcIterator send = s + shape[0];
420 template <
class SrcIterator,
class Shape,
class T,
class Functor,
int N>
422 reduceOverMultiArray(SrcIterator s, Shape
const & shape, T & result, Functor
const & f, MetaInt<N>)
424 SrcIterator send = s + shape[N];
427 reduceOverMultiArray(s.begin(), shape, result, f, MetaInt<N-1>());
431 struct MaxNormReduceFunctor
433 template <
class T,
class U>
434 void operator()(T & result, U
const & u)
const
442 struct L1NormReduceFunctor
444 template <
class T,
class U>
445 void operator()(T & result, U
const & u)
const
451 struct SquaredL2NormReduceFunctor
453 template <
class T,
class U>
454 void operator()(T & result, U
const & u)
const
461 struct WeightedL2NormReduceFunctor
465 WeightedL2NormReduceFunctor(T s)
470 void operator()(T & result, U
const & u)
const
476 struct SumReduceFunctor
478 template <
class T,
class U>
479 void operator()(T & result, U
const & u)
const
485 struct ProdReduceFunctor
487 template <
class T,
class U>
488 void operator()(T & result, U
const & u)
const
494 struct MinmaxReduceFunctor
496 template <
class T,
class U>
497 void operator()(T & result, U
const & u)
const
501 if(result.second < u)
506 struct MeanVarianceReduceFunctor
508 template <
class T,
class U>
509 void operator()(T & result, U
const & u)
const
512 typename T::second_type t1 = u - result.second;
513 typename T::second_type t2 = t1 / result.first;
515 result.third += (result.first-1.0)*t1*t2;
519 struct AllTrueReduceFunctor
521 template <
class T,
class U>
522 void operator()(T & result, U
const & u)
const
524 result = result && (u != NumericTraits<U>::zero());
528 struct AnyTrueReduceFunctor
530 template <
class T,
class U>
531 void operator()(T & result, U
const & u)
const
533 result = result || (u != NumericTraits<U>::zero());
537 template <
class SrcIterator,
class Shape,
class DestIterator>
539 equalityOfMultiArrays(SrcIterator s, Shape
const & shape, DestIterator d, MetaInt<0>)
541 SrcIterator send = s + shape[0];
542 for(; s < send; ++s, ++d)
550 template <
class SrcIterator,
class Shape,
class DestIterator,
int N>
552 equalityOfMultiArrays(SrcIterator s, Shape
const & shape, DestIterator d, MetaInt<N>)
554 SrcIterator send = s + shape[N];
555 for(; s < send; ++s, ++d)
557 if(!equalityOfMultiArrays(s.begin(), shape, d.begin(), MetaInt<N-1>()))
564 template <
class SrcIterator,
class Shape,
class DestIterator>
566 swapDataImpl(SrcIterator s, Shape
const & shape, DestIterator d, MetaInt<0>)
568 SrcIterator send = s + shape[0];
569 for(; s < send; ++s, ++d)
573 template <
class SrcIterator,
class Shape,
class DestIterator,
int N>
575 swapDataImpl(SrcIterator s, Shape
const & shape, DestIterator d, MetaInt<N>)
577 SrcIterator send = s + shape[N];
578 for(; s < send; ++s, ++d)
579 swapDataImpl(s.begin(), shape, d.begin(), MetaInt<N-1>());
592 template <
unsigned int N,
class T,
class C = Unstr
idedArrayTag>
594 template <
unsigned int N,
class T,
class A = std::allocator<T> >
597 namespace multi_math {
600 struct MultiMathOperand;
604 template <
unsigned int N,
class T,
class C,
class E>
607 template <
unsigned int N,
class T,
class C,
class E>
610 template <
unsigned int N,
class T,
class C,
class E>
613 template <
unsigned int N,
class T,
class C,
class E>
616 template <
unsigned int N,
class T,
class C,
class E>
619 template <
unsigned int N,
class T,
class A,
class E>
622 template <
unsigned int N,
class T,
class A,
class E>
625 template <
unsigned int N,
class T,
class A,
class E>
628 template <
unsigned int N,
class T,
class A,
class E>
631 template <
unsigned int N,
class T,
class A,
class E>
638 template <
class T>
class FindSum;
640 struct UnsuitableTypeForExpandElements {};
643 struct ExpandElementResult
645 typedef UnsuitableTypeForExpandElements type;
649 struct ExpandElementResult<std::complex<T> >
659 struct ExpandElementResult<FFTWComplex<T> >
665 template <
class T,
int SIZE>
666 struct ExpandElementResult<TinyVector<T, SIZE> >
669 enum { size = SIZE };
672 template <
class T,
unsigned int R,
unsigned int G,
unsigned int B>
673 struct ExpandElementResult<RGBValue<T, R, G, B> >
679 #define VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(TYPE) \
681 struct ExpandElementResult<TYPE> \
687 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
bool)
688 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
char)
689 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
signed char)
690 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
signed short)
691 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
signed int)
692 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
signed long)
693 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
signed long long)
694 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
unsigned char)
695 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
unsigned short)
696 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
unsigned int)
697 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
unsigned long)
698 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
unsigned long long)
699 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
float)
700 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
double)
701 VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(
long double)
703 #undef VIGRA_DEFINE_EXPAND_ELEMENT_RESULT
712 template <
unsigned int N,
class T,
class C>
713 struct NormTraits<MultiArrayView<N, T, C> >
715 typedef MultiArrayView<N, T, C> Type;
716 typedef typename NormTraits<T>::SquaredNormType SquaredNormType;
717 typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
720 template <
unsigned int N,
class T,
class A>
721 struct NormTraits<MultiArray<N, T, A> >
722 :
public NormTraits<MultiArrayView<N, T, UnstridedArrayTag> >
724 typedef NormTraits<MultiArrayView<N, T, UnstridedArrayTag> > BaseType;
725 typedef MultiArray<N, T, A> Type;
726 typedef typename BaseType::SquaredNormType SquaredNormType;
727 typedef typename BaseType::NormType NormType;
765 template <
unsigned int N,
class T,
class Str
ideTag>
821 typedef typename vigra::detail::MultiIteratorChooser <
822 StrideTag>::template Traverser <actual_dimension, T, T &, T *>::type
traverser;
826 typedef typename vigra::detail::MultiIteratorChooser <
827 StrideTag>::template Traverser <actual_dimension, T, T const &, T const *>::type
const_traverser;
839 typedef typename difference_type::value_type diff_zero_t;
854 template <
class U,
class CN>
857 template <
class U,
class CN>
863 template <
class U,
class CN>
871 return m_stride[0] <= 1;
874 bool checkInnerStride(StridedArrayTag)
885 : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0)
892 m_stride (detail::defaultStride <
MultiArrayView<N,T>::actual_dimension> (shape)),
902 const difference_type &
stride,
908 vigra_precondition(checkInnerStride(StrideTag()),
909 "MultiArrayView<..., UnstridedArrayTag>::MultiArrayView(): First dimension of given array is not unstrided.");
933 template<
class U,
class C1>
936 vigra_precondition(this->
shape() == rhs.shape(),
937 "MultiArrayView::operator=() size mismatch.");
952 template<
class U,
class C1>
958 template<
class U,
class C1>
964 template<
class U,
class C1>
970 template<
class U,
class C1>
977 detail::copyAddScalarMultiArrayData(
traverser_begin(),
shape(), rhs, MetaInt<actual_dimension-1>());
985 detail::copySubScalarMultiArrayData(
traverser_begin(),
shape(), rhs, MetaInt<actual_dimension-1>());
993 detail::copyMulScalarMultiArrayData(
traverser_begin(),
shape(), rhs, MetaInt<actual_dimension-1>());
1001 detail::copyDivScalarMultiArrayData(
traverser_begin(),
shape(), rhs, MetaInt<actual_dimension-1>());
1008 template<
class Expression>
1011 multi_math::detail::assign(*
this, rhs);
1018 template<
class Expression>
1021 multi_math::detail::plusAssign(*
this, rhs);
1028 template<
class Expression>
1031 multi_math::detail::minusAssign(*
this, rhs);
1038 template<
class Expression>
1041 multi_math::detail::multiplyAssign(*
this, rhs);
1048 template<
class Expression>
1051 multi_math::detail::divideAssign(*
this, rhs);
1059 VIGRA_ASSERT_INSIDE(d);
1060 return m_ptr [
dot (d, m_stride)];
1067 VIGRA_ASSERT_INSIDE(d);
1068 return m_ptr [
dot (d, m_stride)];
1092 return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
1108 return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
1115 difference_type result;
1116 detail::ScanOrderToCoordinate<actual_dimension>::exec(d, m_shape, result);
1124 return detail::CoordinateToScanOrder<actual_dimension>::exec(m_shape, d);
1132 return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x)];
1140 return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x, y)];
1145 reference
operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z)
1148 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
1154 difference_type_1 z, difference_type_1 u)
1157 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
1162 reference
operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z,
1163 difference_type_1 u, difference_type_1 v)
1166 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
1174 return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x)];
1179 const_reference
operator() (difference_type_1 x, difference_type_1 y)
const
1182 return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x, y)];
1187 const_reference
operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z)
const
1190 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
1195 const_reference
operator() (difference_type_1 x, difference_type_1 y,
1196 difference_type_1 z, difference_type_1 u)
const
1199 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
1204 const_reference
operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z,
1205 difference_type_1 u, difference_type_1 v)
const
1208 return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
1217 detail::copyScalarMultiArrayData(
traverser_begin(),
shape(), init, MetaInt<actual_dimension-1>());
1228 this->copyImpl(rhs);
1233 template <
class U,
class CN>
1236 this->copyImpl(rhs);
1253 template <
class T2,
class C2>
1268 for(
unsigned int k = dimension+1; k < N; ++k)
1287 template <
int M,
class Index>
1304 template <
int M,
class Index>
1324 template <
unsigned int M>
1325 MultiArrayView <N-1, T,
typename vigra::detail::MaybeStrided<StrideTag, M>::type >
1326 bind (difference_type_1 d)
const;
1375 bindAt (difference_type_1 m, difference_type_1 d)
const;
1396 vigra_precondition(0 <= i && i < ExpandElementResult<T>::size,
1397 "MultiArrayView::bindElementChannel(i): 'i' out of range.");
1490 const difference_type &q)
const
1492 const difference_type_1 offset =
dot (m_stride, p);
1505 difference_type shape =
m_shape;
1506 for (
unsigned int i = 0; i < actual_dimension; ++i)
1529 difference_type
shape(m_shape.begin(), difference_type::ReverseCopy),
1530 stride(m_stride.begin(), difference_type::ReverseCopy);
1585 difference_type_1 ret = m_shape[0];
1586 for(
int i = 1; i < actual_dimension; ++i)
1608 difference_type_1
size (difference_type_1 n)
const
1616 difference_type_1
shape (difference_type_1 n)
const
1632 return m_stride [n];
1637 template <
class U,
class C1>
1640 if(this->
shape() != rhs.shape())
1642 return detail::equalityOfMultiArrays(
traverser_begin(),
shape(), rhs.traverser_begin(), MetaInt<actual_dimension-1>());
1648 template <
class U,
class C1>
1658 for(
int d=0; d<actual_dimension; ++d)
1659 if(p[d] < 0 || p[d] >=
shape(d))
1672 detail::AllTrueReduceFunctor(),
1673 MetaInt<actual_dimension-1>());
1685 detail::AnyTrueReduceFunctor(),
1686 MetaInt<actual_dimension-1>());
1696 std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min());
1699 detail::MinmaxReduceFunctor(),
1700 MetaInt<actual_dimension-1>());
1701 *minimum = res.first;
1702 *maximum = res.second;
1712 typedef typename NumericTraits<U>::RealPromote R;
1714 triple<double, R, R> res(0.0, zero, zero);
1717 detail::MeanVarianceReduceFunctor(),
1718 MetaInt<actual_dimension-1>());
1720 *variance = res.third / res.first;
1735 U res = NumericTraits<U>::zero();
1738 detail::SumReduceFunctor(),
1739 MetaInt<actual_dimension-1>());
1768 template <
class U,
class S>
1772 destMultiArrayRange(sums),
1788 U res = NumericTraits<U>::one();
1791 detail::ProdReduceFunctor(),
1792 MetaInt<actual_dimension-1>());
1798 typename NormTraits<MultiArrayView>::SquaredNormType
1801 typedef typename NormTraits<MultiArrayView>::SquaredNormType SquaredNormType;
1802 SquaredNormType res = NumericTraits<SquaredNormType>::zero();
1805 detail::SquaredL2NormReduceFunctor(),
1806 MetaInt<actual_dimension-1>());
1823 typename NormTraits<MultiArrayView>::NormType
1824 norm(
int type = 2,
bool useSquaredNorm =
true)
const;
1833 pointer & unsafePtr()
1853 return iterator(m_ptr, m_shape, m_stride);
1869 return begin().getEndIterator();
1877 return begin().getEndIterator();
1885 traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1894 const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1904 traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1905 ret += m_shape [actual_dimension-1];
1915 const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1916 ret += m_shape [actual_dimension-1];
1926 template <
unsigned int N,
class T,
class Str
ideTag>
1927 MultiArrayView<N, T, StrideTag> &
1932 vigra_precondition(this->
shape() == rhs.shape() ||
m_ptr == 0,
1933 "MultiArrayView::operator=(MultiArrayView const &) size mismatch.");
1941 this->copyImpl(rhs);
1945 template <
unsigned int N,
class T,
class Str
ideTag>
1950 vigra_precondition (shape () == rhs.shape (),
1951 "MultiArrayView::arraysOverlap(): shape mismatch.");
1955 rhs_first_element = rhs.data(),
1956 rhs_last_element = rhs_first_element +
dot(rhs.shape() -
difference_type(1), rhs.stride());
1957 return !(last_element < rhs_first_element || rhs_last_element < first_element);
1960 template <
unsigned int N,
class T,
class Str
ideTag>
1961 template <
class U,
class CN>
1963 MultiArrayView <N, T, StrideTag>::copyImpl(
const MultiArrayView <N, U, CN>& rhs)
1965 if(!arraysOverlap(rhs))
1968 detail::copyMultiArrayData(rhs.traverser_begin(),
shape(),
traverser_begin(), MetaInt<actual_dimension-1>());
1974 MultiArray<N, T> tmp(rhs);
1975 detail::copyMultiArrayData(tmp.traverser_begin(),
shape(),
traverser_begin(), MetaInt<actual_dimension-1>());
1979 #define VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(name, op) \
1980 template <unsigned int N, class T, class StrideTag> \
1981 template<class U, class C1> \
1982 MultiArrayView<N, T, StrideTag> & \
1983 MultiArrayView <N, T, StrideTag>::operator op(MultiArrayView<N, U, C1> const & rhs) \
1985 vigra_precondition(this->shape() == rhs.shape(), "MultiArrayView::operator" #op "() size mismatch."); \
1986 if(!arraysOverlap(rhs)) \
1988 detail::name##MultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>()); \
1992 MultiArray<N, T> tmp(rhs); \
1993 detail::name##MultiArrayData(tmp.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>()); \
1998 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyAdd, +=)
1999 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copySub, -=)
2000 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyMul, *=)
2001 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyDiv, /=)
2003 #undef VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT
2005 template <
unsigned int N,
class T,
class Str
ideTag>
2006 template <
class U,
class CN>
2008 MultiArrayView <N, T, StrideTag>::swapDataImpl(MultiArrayView <N, U, CN> rhs)
2010 vigra_precondition (shape () == rhs.shape (),
2011 "MultiArrayView::swapData(): shape mismatch.");
2016 typename MultiArrayView <N, U, CN>::const_pointer
2017 rhs_first_element = rhs.
data(),
2018 rhs_last_element = rhs_first_element +
dot(rhs.shape() -
difference_type(1), rhs.stride());
2019 if(last_element < rhs_first_element || rhs_last_element < first_element)
2022 detail::swapDataImpl(
traverser_begin(),
shape(), rhs.traverser_begin(), MetaInt<actual_dimension-1>());
2028 MultiArray<N, T> tmp(*
this);
2034 template <
unsigned int N,
class T,
class Str
ideTag>
2035 MultiArrayView <N, T, StridedArrayTag>
2039 for (
unsigned int i = 0; i < actual_dimension; ++i)
2046 "MultiArrayView::permuteDimensions(): every dimension must occur exactly once.");
2050 template <
unsigned int N,
class T,
class Str
ideTag>
2055 for(
int k=0; k<(int)N; ++k)
2057 for(
int k=0; k<(int)N-1; ++k)
2060 for(
int j=k+1; j<(int)N; ++j)
2068 std::swap(permutation[k], permutation[smallest]);
2072 for(
unsigned int k=0; k<N; ++k)
2073 ordering[permutation[k]] = k;
2077 template <
unsigned int N,
class T,
class Str
ideTag>
2083 permutation[ordering[k]] = k;
2087 template <
unsigned int N,
class T,
class Str
ideTag>
2093 permutation[ordering[N-1-k]] = k;
2097 template <
unsigned int N,
class T,
class Str
ideTag>
2098 template <
int M,
class Index>
2105 static const int NNew = (N-M == 0) ? 1 : N-M;
2109 inner_shape [0] = 1;
2110 inner_stride [0] = 0;
2117 return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, ptr);
2120 template <
unsigned int N,
class T,
class Str
ideTag>
2121 template <
int M,
class Index>
2128 static const int NNew = (N-M == 0) ? 1 : N-M;
2132 outer_shape [0] = 1;
2133 outer_stride [0] = 0;
2141 (outer_shape, outer_stride, ptr);
2144 template <
unsigned int N,
class T,
class Str
ideTag>
2145 template <
unsigned int M>
2146 MultiArrayView <N-1, T,
typename detail::MaybeStrided<StrideTag, M>::type >
2149 static const int NNew = (N-1 == 0) ? 1 : N-1;
2161 shape.
begin () + M);
2164 stride.
begin () + M);
2166 return MultiArrayView <N-1, T,
typename detail::MaybeStrided<StrideTag, M>::type>
2170 template <
unsigned int N,
class T,
class Str
ideTag>
2174 static const int NNew = (N-1 == 0) ? 1 : N-1;
2178 inner_shape [0] = 1;
2179 inner_stride [0] = 0;
2186 return MultiArrayView <N-1, T, StrideTag> (inner_shape, inner_stride,
2190 template <
unsigned int N,
class T,
class Str
ideTag>
2194 static const int NNew = (N-1 == 0) ? 1 : N-1;
2198 outer_shape [0] = 1;
2199 outer_stride [0] = 0;
2210 template <
unsigned int N,
class T,
class Str
ideTag>
2214 vigra_precondition (
2215 n < static_cast <int> (N),
2216 "MultiArrayView <N, T, StrideTag>::bindAt(): dimension out of range.");
2217 static const int NNew = (N-1 == 0) ? 1 : N-1;
2229 shape.
begin () + n);
2232 stride.
begin () + n);
2239 template <
unsigned int N,
class T,
class Str
ideTag>
2243 vigra_precondition(0 <= d && d <= static_cast <difference_type_1> (N),
2244 "MultiArrayView<N, ...>::expandElements(d): 0 <= 'd' <= N required.");
2246 int elementSize = ExpandElementResult<T>::size;
2248 for(
int k=0; k<d; ++k)
2251 newStrides[k] =
m_stride[k]*elementSize;
2254 newShape[d] = elementSize;
2257 for(
int k=d; k<N; ++k)
2260 newStrides[k+1] =
m_stride[k]*elementSize;
2263 typedef typename ExpandElementResult<T>::type U;
2265 newShape, newStrides,
reinterpret_cast<U*
>(
m_ptr));
2268 template <
unsigned int N,
class T,
class Str
ideTag>
2272 vigra_precondition (
2273 0 <= i && i <= static_cast <difference_type_1> (N),
2274 "MultiArrayView <N, T, StrideTag>::insertSingletonDimension(): index out of range.");
2286 template <
unsigned int N,
class T,
class Str
ideTag>
2287 typename NormTraits<MultiArrayView <N, T, StrideTag> >::NormType
2290 typedef typename NormTraits<MultiArrayView>::NormType NormType;
2296 NormType res = NumericTraits<NormType>::zero();
2299 detail::MaxNormReduceFunctor(),
2300 MetaInt<actual_dimension-1>());
2305 NormType res = NumericTraits<NormType>::zero();
2308 detail::L1NormReduceFunctor(),
2309 MetaInt<actual_dimension-1>());
2320 NormType normMax = NumericTraits<NormType>::zero();
2323 detail::MaxNormReduceFunctor(),
2324 MetaInt<actual_dimension-1>());
2325 if(normMax == NumericTraits<NormType>::zero())
2327 NormType res = NumericTraits<NormType>::zero();
2330 detail::WeightedL2NormReduceFunctor<NormType>(1.0/normMax),
2331 MetaInt<actual_dimension-1>());
2332 return sqrt(res)*normMax;
2336 vigra_precondition(
false,
"MultiArrayView::norm(): Unknown norm type.");
2337 return NumericTraits<NormType>::zero();
2348 template <
unsigned int N,
class T,
class Str
ideTag>
2349 inline typename NormTraits<MultiArrayView <N, T, StrideTag> >::SquaredNormType
2355 template <
unsigned int N,
class T,
class Str
ideTag>
2356 inline typename NormTraits<MultiArrayView <N, T, StrideTag> >::NormType
2357 norm(MultiArrayView <N, T, StrideTag>
const & a)
2391 template <
unsigned int N,
class T,
class A >
2396 using MultiArrayView <N, T>::actual_dimension;
2444 typedef typename vigra::detail::MultiIteratorChooser <
2450 typedef typename vigra::detail::MultiIteratorChooser <
2464 typedef typename difference_type::value_type diff_zero_t;
2484 template <
class U,
class Str
ideTag>
2491 template <
class U,
class Str
ideTag>
2514 allocator_type
const & alloc = allocator_type());
2519 allocator_type
const & alloc = allocator_type());
2524 allocator_type
const & alloc = allocator_type());
2529 allocator_type
const & alloc = allocator_type());
2535 m_alloc (rhs.m_alloc)
2542 template<
class Expression>
2543 MultiArray (multi_math::MultiMathOperand<Expression>
const & rhs,
2549 multi_math::detail::assignOrResize(*
this, rhs);
2554 template <
class U,
class Str
ideTag>
2556 allocator_type
const & alloc = allocator_type());
2566 this->copyOrReshape(rhs);
2575 template <
class U,
class Str
ideTag>
2578 this->copyOrReshape(rhs);
2587 return this->
init(v);
2596 template <
class U,
class Str
ideTag>
2612 template <
class U,
class Str
ideTag>
2616 this->reshape(rhs.shape());
2627 template <
class U,
class Str
ideTag>
2633 this->reshape(rhs.shape());
2643 template <
class U,
class Str
ideTag>
2649 this->reshape(rhs.shape());
2687 template<
class Expression>
2690 multi_math::detail::assignOrResize(*
this, rhs);
2697 template<
class Expression>
2700 multi_math::detail::plusAssignOrResize(*
this, rhs);
2707 template<
class Expression>
2710 multi_math::detail::minusAssignOrResize(*
this, rhs);
2717 template<
class Expression>
2720 multi_math::detail::multiplyAssignOrResize(*
this, rhs);
2727 template<
class Expression>
2730 multi_math::detail::divideAssignOrResize(*
this, rhs);
2757 reshape (shape, T());
2778 return this->
data();
2792 return this->
data();
2810 template <
unsigned int N,
class T,
class A>
2821 template <
unsigned int N,
class T,
class A>
2837 template <
unsigned int N,
class T,
class A>
2853 template <
unsigned int N,
class T,
class A>
2869 template <
unsigned int N,
class T,
class A>
2870 template <
class U,
class Str
ideTag>
2874 detail::defaultStride <MultiArrayView<N,T>::actual_dimension>(rhs.shape()),
2878 allocate (this->
m_ptr, rhs);
2881 template <
unsigned int N,
class T,
class A>
2882 template <
class U,
class Str
ideTag>
2886 if (this->
shape() == rhs.shape())
2895 template <
unsigned int N,
class T,
class A>
2903 else if(new_shape == this->
shape())
2905 this->
init(initial);
2909 difference_type new_stride = detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (new_shape);
2912 allocate (new_ptr, new_size, initial);
2914 this->
m_ptr = new_ptr;
2921 template <
unsigned int N,
class T,
class A>
2927 std::swap(this->
m_shape, other.m_shape);
2928 std::swap(this->
m_stride, other.m_stride);
2929 std::swap(this->
m_ptr, other.m_ptr);
2930 std::swap(this->m_alloc, other.m_alloc);
2933 template <
unsigned int N,
class T,
class A>
2937 ptr = m_alloc.
allocate ((
typename A::size_type)s);
2940 for (i = 0; i < s; ++i)
2941 m_alloc.construct (ptr + i, init);
2945 m_alloc.destroy (ptr + j);
2946 m_alloc.deallocate (ptr, (
typename A::size_type)s);
2951 template <
unsigned int N,
class T,
class A>
2956 ptr = m_alloc.
allocate ((
typename A::size_type)s);
2959 for (i = 0; i < s; ++i, ++
init)
2960 m_alloc.construct (ptr + i, *init);
2964 m_alloc.destroy (ptr + j);
2965 m_alloc.deallocate (ptr, (
typename A::size_type)s);
2970 template <
unsigned int N,
class T,
class A>
2971 template <
class U,
class Str
ideTag>
2975 ptr = m_alloc.allocate ((
typename A::size_type)s);
2978 detail::uninitializedCopyMultiArrayData(init.traverser_begin(), init.shape(),
2979 p, m_alloc, MetaInt<actual_dimension-1>());
2982 for (
pointer pp = ptr; pp < p; ++pp)
2983 m_alloc.destroy (pp);
2984 m_alloc.deallocate (ptr, (
typename A::size_type)s);
2989 template <
unsigned int N,
class T,
class A>
2995 m_alloc.destroy (ptr + i);
2996 m_alloc.
deallocate (ptr, (
typename A::size_type)s);
3006 template <
unsigned int N,
class T,
class Str
ideTag>
3007 inline triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3012 return triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3020 template <
unsigned int N,
class T,
class Str
ideTag,
class Accessor>
3021 inline triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3022 typename MultiArrayView<N,T,StrideTag>::difference_type,
3024 srcMultiArrayRange( MultiArrayView<N,T,StrideTag>
const & array, Accessor a )
3026 return triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3027 typename MultiArrayView<N,T,StrideTag>::difference_type,
3029 ( array.traverser_begin(),
3034 template <
unsigned int N,
class T,
class Str
ideTag>
3035 inline pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3036 typename AccessorTraits<T>::default_const_accessor >
3037 srcMultiArray( MultiArrayView<N,T,StrideTag>
const & array )
3039 return pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3040 typename AccessorTraits<T>::default_const_accessor >
3041 ( array.traverser_begin(),
3042 typename AccessorTraits<T>::default_const_accessor() );
3045 template <
unsigned int N,
class T,
class Str
ideTag,
class Accessor>
3046 inline pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3048 srcMultiArray( MultiArrayView<N,T,StrideTag>
const & array, Accessor a )
3050 return pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3052 ( array.traverser_begin(), a );
3055 template <
unsigned int N,
class T,
class Str
ideTag>
3056 inline triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3057 typename MultiArrayView<N,T,StrideTag>::difference_type,
3058 typename AccessorTraits<T>::default_accessor >
3059 destMultiArrayRange( MultiArrayView<N,T,StrideTag> & array )
3061 return triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3062 typename MultiArrayView<N,T,StrideTag>::difference_type,
3063 typename AccessorTraits<T>::default_accessor >
3064 ( array.traverser_begin(),
3066 typename AccessorTraits<T>::default_accessor() );
3069 template <
unsigned int N,
class T,
class Str
ideTag,
class Accessor>
3070 inline triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3071 typename MultiArrayView<N,T,StrideTag>::difference_type,
3073 destMultiArrayRange( MultiArrayView<N,T,StrideTag> & array, Accessor a )
3075 return triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3076 typename MultiArrayView<N,T,StrideTag>::difference_type,
3078 ( array.traverser_begin(),
3083 template <
unsigned int N,
class T,
class Str
ideTag>
3084 inline pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3085 typename AccessorTraits<T>::default_accessor >
3086 destMultiArray( MultiArrayView<N,T,StrideTag> & array )
3088 return pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3089 typename AccessorTraits<T>::default_accessor >
3090 ( array.traverser_begin(),
3091 typename AccessorTraits<T>::default_accessor() );
3094 template <
unsigned int N,
class T,
class Str
ideTag,
class Accessor>
3095 inline pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3097 destMultiArray( MultiArrayView<N,T,StrideTag> & array, Accessor a )
3099 return pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3101 ( array.traverser_begin(), a );
3106 template <
class PixelType,
class Accessor>
3107 inline triple<ConstStridedImageIterator<PixelType>,
3108 ConstStridedImageIterator<PixelType>, Accessor>
3109 srcImageRange(
const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3111 ConstStridedImageIterator<PixelType>
3112 ul(img.data(), 1, img.stride(0), img.stride(1));
3113 return triple<ConstStridedImageIterator<PixelType>,
3114 ConstStridedImageIterator<PixelType>,
3116 ul, ul + Size2D(img.shape(0), img.shape(1)), a);
3119 template <
class PixelType,
class Accessor>
3120 inline pair<ConstStridedImageIterator<PixelType>, Accessor>
3121 srcImage(
const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3123 ConstStridedImageIterator<PixelType>
3124 ul(img.data(), 1, img.stride(0), img.stride(1));
3125 return pair<ConstStridedImageIterator<PixelType>, Accessor>
3129 template <
class PixelType,
class Accessor>
3130 inline triple<StridedImageIterator<PixelType>,
3131 StridedImageIterator<PixelType>, Accessor>
3132 destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3134 StridedImageIterator<PixelType>
3135 ul(img.data(), 1, img.stride(0), img.stride(1));
3136 return triple<StridedImageIterator<PixelType>,
3137 StridedImageIterator<PixelType>,
3139 ul, ul + Size2D(img.shape(0), img.shape(1)), a);
3142 template <
class PixelType,
class Accessor>
3143 inline pair<StridedImageIterator<PixelType>, Accessor>
3144 destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3146 StridedImageIterator<PixelType>
3147 ul(img.data(), 1, img.stride(0), img.stride(1));
3148 return pair<StridedImageIterator<PixelType>, Accessor>
3152 template <
class PixelType,
class Accessor>
3153 inline pair<StridedImageIterator<PixelType>, Accessor>
3154 maskImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3156 StridedImageIterator<PixelType>
3157 ul(img.data(), 1, img.stride(0), img.stride(1));
3158 return pair<StridedImageIterator<PixelType>, Accessor>
3164 template <
class PixelType>
3165 inline triple<ConstStridedImageIterator<PixelType>,
3166 ConstStridedImageIterator<PixelType>,
3167 typename AccessorTraits<PixelType>::default_const_accessor>
3168 srcImageRange(MultiArrayView<2, PixelType, StridedArrayTag>
const & img)
3170 ConstStridedImageIterator<PixelType>
3171 ul(img.data(), 1, img.stride(0), img.stride(1));
3172 typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3173 return triple<ConstStridedImageIterator<PixelType>,
3174 ConstStridedImageIterator<PixelType>,
3176 (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3179 template <
class PixelType>
3180 inline triple<ConstImageIterator<PixelType>,
3181 ConstImageIterator<PixelType>,
3182 typename AccessorTraits<PixelType>::default_const_accessor>
3183 srcImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag>
const & img)
3185 ConstImageIterator<PixelType>
3186 ul(img.data(), img.stride(1));
3187 typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3188 return triple<ConstImageIterator<PixelType>,
3189 ConstImageIterator<PixelType>,
3191 (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3194 template <
class PixelType>
3195 inline pair< ConstStridedImageIterator<PixelType>,
3196 typename AccessorTraits<PixelType>::default_const_accessor>
3197 srcImage(MultiArrayView<2, PixelType, StridedArrayTag>
const & img)
3199 ConstStridedImageIterator<PixelType>
3200 ul(img.data(), 1, img.stride(0), img.stride(1));
3201 typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3202 return pair<ConstStridedImageIterator<PixelType>,
3207 template <
class PixelType>
3208 inline pair< ConstImageIterator<PixelType>,
3209 typename AccessorTraits<PixelType>::default_const_accessor>
3210 srcImage(MultiArrayView<2, PixelType, UnstridedArrayTag>
const & img)
3212 ConstImageIterator<PixelType>
3213 ul(img.data(), img.stride(1));
3214 typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3215 return pair<ConstImageIterator<PixelType>,
3220 template <
class PixelType>
3221 inline triple< StridedImageIterator<PixelType>,
3222 StridedImageIterator<PixelType>,
3223 typename AccessorTraits<PixelType>::default_accessor>
3224 destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img)
3226 StridedImageIterator<PixelType>
3227 ul(img.data(), 1, img.stride(0), img.stride(1));
3228 typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3229 return triple<StridedImageIterator<PixelType>,
3230 StridedImageIterator<PixelType>,
3232 (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3235 template <
class PixelType>
3236 inline triple< ImageIterator<PixelType>,
3237 ImageIterator<PixelType>,
3238 typename AccessorTraits<PixelType>::default_accessor>
3239 destImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag> & img)
3241 ImageIterator<PixelType>
3242 ul(img.data(), img.stride(1));
3243 typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3244 return triple<ImageIterator<PixelType>,
3245 ImageIterator<PixelType>,
3247 (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3250 template <
class PixelType>
3251 inline pair< StridedImageIterator<PixelType>,
3252 typename AccessorTraits<PixelType>::default_accessor>
3253 destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img)
3255 StridedImageIterator<PixelType>
3256 ul(img.data(), 1, img.stride(0), img.stride(1));
3257 typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3258 return pair<StridedImageIterator<PixelType>, Accessor>
3262 template <
class PixelType>
3263 inline pair< ImageIterator<PixelType>,
3264 typename AccessorTraits<PixelType>::default_accessor>
3265 destImage(MultiArrayView<2, PixelType, UnstridedArrayTag> & img)
3267 ImageIterator<PixelType> ul(img.data(), img.stride(1));
3268 typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3269 return pair<ImageIterator<PixelType>, Accessor>(ul, Accessor());
3272 template <
class PixelType>
3273 inline pair< ConstStridedImageIterator<PixelType>,
3274 typename AccessorTraits<PixelType>::default_accessor>
3275 maskImage(MultiArrayView<2, PixelType, StridedArrayTag>
const & img)
3277 ConstStridedImageIterator<PixelType>
3278 ul(img.data(), 1, img.stride(0), img.stride(1));
3279 typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3280 return pair<ConstStridedImageIterator<PixelType>, Accessor>
3284 template <
class PixelType>
3285 inline pair< ConstImageIterator<PixelType>,
3286 typename AccessorTraits<PixelType>::default_accessor>
3287 maskImage(MultiArrayView<2, PixelType, UnstridedArrayTag>
const & img)
3289 ConstImageIterator<PixelType>
3290 ul(img.data(), img.stride(1));
3291 typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3292 return pair<ConstImageIterator<PixelType>, Accessor>
3345 BasicImageView <RGBValue<T> >
3348 vigra_precondition (
3349 array.shape (0) == 3,
"makeRGBImageView(): array.shape(0) must be 3.");
3352 array.shape (1), array.shape (2));
3359 #undef VIGRA_ASSERT_INSIDE
3361 #endif // VIGRA_MULTI_ARRAY_HXX