[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

multi_array.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_MULTI_ARRAY_HXX
38 #define VIGRA_MULTI_ARRAY_HXX
39 
40 #include <memory>
41 #include <algorithm>
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"
51 
52 // Bounds checking Macro used if VIGRA_CHECK_BOUNDS is defined.
53 #ifdef VIGRA_CHECK_BOUNDS
54 #define VIGRA_ASSERT_INSIDE(diff) \
55  vigra_precondition(this->isInside(diff), "Index out of bounds")
56 #else
57 #define VIGRA_ASSERT_INSIDE(diff)
58 #endif
59 
60 namespace vigra
61 {
62 
63 namespace detail
64 {
65 /********************************************************/
66 /* */
67 /* defaultStride */
68 /* */
69 /********************************************************/
70 
71 /* generates the stride for a gapless shape.
72 
73  Namespace: vigra::detail
74 */
75 template <unsigned int N>
76 inline TinyVector <MultiArrayIndex, N>
77 defaultStride(const TinyVector <MultiArrayIndex, N> &shape)
78 {
79  TinyVector <MultiArrayIndex, N> ret;
80  ret [0] = 1;
81  for (int i = 1; i < (int)N; ++i)
82  ret [i] = ret [i-1] * shape [i-1];
83  return ret;
84 }
85 
86 /********************************************************/
87 /* */
88 /* ScanOrderToOffset */
89 /* */
90 /********************************************************/
91 
92 /* transforms an index in scan order sense to a pointer offset in a possibly
93  strided, multi-dimensional array.
94 
95  Namespace: vigra::detail
96 */
97 
98 template <int K>
99 struct ScanOrderToOffset
100 {
101  template <int N>
102  static MultiArrayIndex
103  exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> &shape,
104  const TinyVector <MultiArrayIndex, N> & stride)
105  {
106  return stride[N-K] * (d % shape[N-K]) +
107  ScanOrderToOffset<K-1>::exec(d / shape[N-K], shape, stride);
108  }
109 };
110 
111 template <>
112 struct ScanOrderToOffset<1>
113 {
114  template <int N>
115  static MultiArrayIndex
116  exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape*/,
117  const TinyVector <MultiArrayIndex, N> & stride)
118  {
119  return stride[N-1] * d;
120  }
121 };
122 
123 template <int K>
124 struct ScanOrderToCoordinate
125 {
126  template <int N>
127  static void
128  exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> &shape,
129  TinyVector <MultiArrayIndex, N> & result)
130  {
131  result[N-K] = (d % shape[N-K]);
132  ScanOrderToCoordinate<K-1>::exec(d / shape[N-K], shape, result);
133  }
134 };
135 
136 template <>
137 struct ScanOrderToCoordinate<1>
138 {
139  template <int N>
140  static void
141  exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape*/,
142  TinyVector <MultiArrayIndex, N> & result)
143  {
144  result[N-1] = d;
145  }
146 };
147 
148 
149 template <class C>
150 struct CoordinatesToOffest
151 {
152  template <int N>
153  static MultiArrayIndex
154  exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x)
155  {
156  return stride[0] * x;
157  }
158  template <int N>
159  static MultiArrayIndex
160  exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x, MultiArrayIndex y)
161  {
162  return stride[0] * x + stride[1] * y;
163  }
164 };
165 
166 template <>
167 struct CoordinatesToOffest<UnstridedArrayTag>
168 {
169  template <int N>
170  static MultiArrayIndex
171  exec(const TinyVector <MultiArrayIndex, N> & /*stride*/, MultiArrayIndex x)
172  {
173  return x;
174  }
175  template <int N>
176  static MultiArrayIndex
177  exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x, MultiArrayIndex y)
178  {
179  return x + stride[1] * y;
180  }
181 };
182 
183 /********************************************************/
184 /* */
185 /* MaybeStrided */
186 /* */
187 /********************************************************/
188 
189 /* metatag implementing a test for marking MultiArrays that were
190  indexed at the zero'th dimension as strided, and all others as
191  unstrided.
192 
193 <b>\#include</b>
194 <vigra/multi_array.hxx>
195 
196 Namespace: vigra::detail
197 */
198 template <class StrideTag, unsigned int N>
199 struct MaybeStrided
200 {
201  typedef StrideTag type;
202 };
203 
204 template <class StrideTag>
205 struct MaybeStrided <StrideTag, 0>
206 {
207  typedef StridedArrayTag type;
208 };
209 
210 /********************************************************/
211 /* */
212 /* MultiIteratorChooser */
213 /* */
214 /********************************************************/
215 
216 /* metatag implementing a test (by pattern matching) for marking
217  MultiArrays that were indexed at the zero'th dimension as strided.
218 
219 <b>\#include</b>
220 <vigra/multi_array.hxx>
221 
222 Namespace: vigra::detail
223 */
224 template <class O>
225 struct MultiIteratorChooser
226 {
227  struct Nil {};
228 
229  template <unsigned int N, class T, class REFERENCE, class POINTER>
230  struct Traverser
231  {
232  typedef Nil type;
233  };
234 };
235 
236 /********************************************************/
237 /* */
238 /* MultiIteratorChooser <StridedArrayTag> */
239 /* */
240 /********************************************************/
241 
242 /* specialization of the MultiIteratorChooser for strided arrays.
243 
244 <b>\#include</b>
245 <vigra/multi_array.hxx>
246 
247 Namespace: vigra::detail
248 */
249 template <>
250 struct MultiIteratorChooser <StridedArrayTag>
251 {
252  template <unsigned int N, class T, class REFERENCE, class POINTER>
253  struct Traverser
254  {
255  typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type;
256  };
257 };
258 
259 /********************************************************/
260 /* */
261 /* MultiIteratorChooser <UnstridedArrayTag> */
262 /* */
263 /********************************************************/
264 
265 /* specialization of the MultiIteratorChooser for unstrided arrays.
266 
267 <b>\#include</b>
268 <vigra/multi_array.hxx>
269 
270 Namespace: vigra::detail
271 */
272 template <>
273 struct MultiIteratorChooser <UnstridedArrayTag>
274 {
275  template <unsigned int N, class T, class REFERENCE, class POINTER>
276  struct Traverser
277  {
278  typedef MultiIterator <N, T, REFERENCE, POINTER> type;
279  };
280 };
281 
282 /********************************************************/
283 /* */
284 /* helper functions */
285 /* */
286 /********************************************************/
287 
288 template <class DestIterator, class Shape, class T>
289 inline void
290 initMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<0>)
291 {
292  DestIterator dend = d + shape[0];
293  for(; d < dend; ++d)
294  {
295  *d = init;
296  }
297 }
298 
299 template <class DestIterator, class Shape, class T, int N>
300 void
301 initMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<N>)
302 {
303  DestIterator dend = d + shape[N];
304  for(; d < dend; ++d)
305  {
306  initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
307  }
308 }
309 
310 // FIXME: the explicit overload for MultiIterator<1, UInt8, ... > works around a compiler crash in VisualStudio 2010
311 #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \
312 template <class SrcIterator, class Shape, class DestIterator> \
313 inline void \
314 name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<0>) \
315 { \
316  SrcIterator send = s + shape[0]; \
317  for(; s < send; ++s, ++d) \
318  { \
319  *d op detail::RequiresExplicitCast<typename DestIterator::value_type>::cast(*s); \
320  } \
321 } \
322  \
323 template <class Ref, class Ptr, class Shape, class DestIterator> \
324 inline void \
325 name##MultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & shape, DestIterator d, MetaInt<0>) \
326 { \
327  Ptr s = &(*si), send = s + shape[0]; \
328  for(; s < send; ++s, ++d) \
329  { \
330  *d op detail::RequiresExplicitCast<typename DestIterator::value_type>::cast(*s); \
331  } \
332 } \
333 \
334 template <class SrcIterator, class Shape, class DestIterator, int N> \
335 void \
336 name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<N>) \
337 { \
338  SrcIterator send = s + shape[N]; \
339  for(; s < send; ++s, ++d) \
340  { \
341  name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>()); \
342  } \
343 } \
344 \
345 template <class DestIterator, class Shape, class T> \
346 inline void \
347 name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<0>) \
348 { \
349  DestIterator dend = d + shape[0]; \
350  for(; d < dend; ++d) \
351  { \
352  *d op detail::RequiresExplicitCast<typename DestIterator::value_type>::cast(init); \
353  } \
354 } \
355  \
356 template <class DestIterator, class Shape, class T, int N> \
357 void \
358 name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & init, MetaInt<N>) \
359 { \
360  DestIterator dend = d + shape[N]; \
361  for(; d < dend; ++d) \
362  { \
363  name##ScalarMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); \
364  } \
365 }
366 
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, /=)
372 
373 #undef VIGRA_COPY_MULTI_ARRAY_DATA
374 
375 template <class SrcIterator, class Shape, class T, class ALLOC>
376 inline void
377 uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d, ALLOC & a, MetaInt<0>)
378 {
379  SrcIterator send = s + shape[0];
380  for(; s < send; ++s, ++d)
381  {
382  a.construct(d, static_cast<T const &>(*s));
383  }
384 }
385 
386 // FIXME: this overload works around a compiler crash in VisualStudio 2010
387 template <class Ref, class Ptr, class Shape, class T, class ALLOC>
388 inline void
389 uninitializedCopyMultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & shape, T * & d, ALLOC & a, MetaInt<0>)
390 {
391  Ptr s = &(*si), send = s + shape[0];
392  for(; s < send; ++s, ++d)
393  {
394  a.construct(d, static_cast<T const &>(*s));
395  }
396 }
397 
398 template <class SrcIterator, class Shape, class T, class ALLOC, int N>
399 void
400 uninitializedCopyMultiArrayData(SrcIterator s, Shape const & shape, T * & d, ALLOC & a, MetaInt<N>)
401 {
402  SrcIterator send = s + shape[N];
403  for(; s < send; ++s)
404  {
405  uninitializedCopyMultiArrayData(s.begin(), shape, d, a, MetaInt<N-1>());
406  }
407 }
408 
409 template <class SrcIterator, class Shape, class T, class Functor>
410 inline void
411 reduceOverMultiArray(SrcIterator s, Shape const & shape, T & result, Functor const & f, MetaInt<0>)
412 {
413  SrcIterator send = s + shape[0];
414  for(; s < send; ++s)
415  {
416  f(result, *s);
417  }
418 }
419 
420 template <class SrcIterator, class Shape, class T, class Functor, int N>
421 void
422 reduceOverMultiArray(SrcIterator s, Shape const & shape, T & result, Functor const & f, MetaInt<N>)
423 {
424  SrcIterator send = s + shape[N];
425  for(; s < send; ++s)
426  {
427  reduceOverMultiArray(s.begin(), shape, result, f, MetaInt<N-1>());
428  }
429 }
430 
431 struct MaxNormReduceFunctor
432 {
433  template <class T, class U>
434  void operator()(T & result, U const & u) const
435  {
436  T v = norm(u);
437  if(result < v)
438  result = v;
439  }
440 };
441 
442 struct L1NormReduceFunctor
443 {
444  template <class T, class U>
445  void operator()(T & result, U const & u) const
446  {
447  result += norm(u);
448  }
449 };
450 
451 struct SquaredL2NormReduceFunctor
452 {
453  template <class T, class U>
454  void operator()(T & result, U const & u) const
455  {
456  result += squaredNorm(u);
457  }
458 };
459 
460 template <class T>
461 struct WeightedL2NormReduceFunctor
462 {
463  T scale;
464 
465  WeightedL2NormReduceFunctor(T s)
466  : scale(s)
467  {}
468 
469  template <class U>
470  void operator()(T & result, U const & u) const
471  {
472  result += squaredNorm(u * scale);
473  }
474 };
475 
476 struct SumReduceFunctor
477 {
478  template <class T, class U>
479  void operator()(T & result, U const & u) const
480  {
481  result += u;
482  }
483 };
484 
485 struct ProdReduceFunctor
486 {
487  template <class T, class U>
488  void operator()(T & result, U const & u) const
489  {
490  result *= u;
491  }
492 };
493 
494 struct MinmaxReduceFunctor
495 {
496  template <class T, class U>
497  void operator()(T & result, U const & u) const
498  {
499  if(u < result.first)
500  result.first = u;
501  if(result.second < u)
502  result.second = u;
503  }
504 };
505 
506 struct MeanVarianceReduceFunctor
507 {
508  template <class T, class U>
509  void operator()(T & result, U const & u) const
510  {
511  ++result.first;
512  typename T::second_type t1 = u - result.second;
513  typename T::second_type t2 = t1 / result.first;
514  result.second += t2;
515  result.third += (result.first-1.0)*t1*t2;
516  }
517 };
518 
519 struct AllTrueReduceFunctor
520 {
521  template <class T, class U>
522  void operator()(T & result, U const & u) const
523  {
524  result = result && (u != NumericTraits<U>::zero());
525  }
526 };
527 
528 struct AnyTrueReduceFunctor
529 {
530  template <class T, class U>
531  void operator()(T & result, U const & u) const
532  {
533  result = result || (u != NumericTraits<U>::zero());
534  }
535 };
536 
537 template <class SrcIterator, class Shape, class DestIterator>
538 inline bool
539 equalityOfMultiArrays(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<0>)
540 {
541  SrcIterator send = s + shape[0];
542  for(; s < send; ++s, ++d)
543  {
544  if(!(*s == *d))
545  return false;
546  }
547  return true;
548 }
549 
550 template <class SrcIterator, class Shape, class DestIterator, int N>
551 bool
552 equalityOfMultiArrays(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<N>)
553 {
554  SrcIterator send = s + shape[N];
555  for(; s < send; ++s, ++d)
556  {
557  if(!equalityOfMultiArrays(s.begin(), shape, d.begin(), MetaInt<N-1>()))
558  return false;
559  }
560  return true;
561 }
562 
563 
564 template <class SrcIterator, class Shape, class DestIterator>
565 inline void
566 swapDataImpl(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<0>)
567 {
568  SrcIterator send = s + shape[0];
569  for(; s < send; ++s, ++d)
570  std::swap(*s, *d);
571 }
572 
573 template <class SrcIterator, class Shape, class DestIterator, int N>
574 void
575 swapDataImpl(SrcIterator s, Shape const & shape, DestIterator d, MetaInt<N>)
576 {
577  SrcIterator send = s + shape[N];
578  for(; s < send; ++s, ++d)
579  swapDataImpl(s.begin(), shape, d.begin(), MetaInt<N-1>());
580 }
581 
582 } // namespace detail
583 
584 /********************************************************/
585 /* */
586 /* MultiArrayView */
587 /* */
588 /********************************************************/
589 
590 // forward declarations
591 
592 template <unsigned int N, class T, class C = UnstridedArrayTag>
594 template <unsigned int N, class T, class A = std::allocator<T> >
596 
597 namespace multi_math {
598 
599 template <class T>
600 struct MultiMathOperand;
601 
602 namespace detail {
603 
604 template <unsigned int N, class T, class C, class E>
605 void assign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &);
606 
607 template <unsigned int N, class T, class C, class E>
608 void plusAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &);
609 
610 template <unsigned int N, class T, class C, class E>
611 void minusAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &);
612 
613 template <unsigned int N, class T, class C, class E>
614 void multiplyAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &);
615 
616 template <unsigned int N, class T, class C, class E>
617 void divideAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &);
618 
619 template <unsigned int N, class T, class A, class E>
620 void assignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &);
621 
622 template <unsigned int N, class T, class A, class E>
623 void plusAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &);
624 
625 template <unsigned int N, class T, class A, class E>
626 void minusAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &);
627 
628 template <unsigned int N, class T, class A, class E>
629 void multiplyAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &);
630 
631 template <unsigned int N, class T, class A, class E>
632 void divideAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &);
633 
634 } // namespace detail
635 
636 } // namespace multi_math
637 
638 template <class T> class FindSum;
639 
640 struct UnsuitableTypeForExpandElements {};
641 
642 template <class T>
643 struct ExpandElementResult
644 {
645  typedef UnsuitableTypeForExpandElements type;
646 };
647 
648 template <class T>
649 struct ExpandElementResult<std::complex<T> >
650 {
651  typedef T type;
652  enum { size = 2 };
653 };
654 
655 template <class T>
656 class FFTWComplex;
657 
658 template <class T>
659 struct ExpandElementResult<FFTWComplex<T> >
660 {
661  typedef T type;
662  enum { size = 2 };
663 };
664 
665 template <class T, int SIZE>
666 struct ExpandElementResult<TinyVector<T, SIZE> >
667 {
668  typedef T type;
669  enum { size = SIZE };
670 };
671 
672 template <class T, unsigned int R, unsigned int G, unsigned int B>
673 struct ExpandElementResult<RGBValue<T, R, G, B> >
674 {
675  typedef T type;
676  enum { size = 3 };
677 };
678 
679 #define VIGRA_DEFINE_EXPAND_ELEMENT_RESULT(TYPE) \
680 template <> \
681 struct ExpandElementResult<TYPE> \
682 { \
683  typedef TYPE type; \
684  enum { size = 1 }; \
685 }; \
686 
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)
702 
703 #undef VIGRA_DEFINE_EXPAND_ELEMENT_RESULT
704 
705 
706 /********************************************************/
707 /* */
708 /* NormTraits */
709 /* */
710 /********************************************************/
711 
712 template <unsigned int N, class T, class C>
713 struct NormTraits<MultiArrayView<N, T, C> >
714 {
715  typedef MultiArrayView<N, T, C> Type;
716  typedef typename NormTraits<T>::SquaredNormType SquaredNormType;
717  typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult NormType;
718 };
719 
720 template <unsigned int N, class T, class A>
721 struct NormTraits<MultiArray<N, T, A> >
722 : public NormTraits<MultiArrayView<N, T, UnstridedArrayTag> >
723 {
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;
728 };
729 
730 /** \brief Base class for, and view to, \ref vigra::MultiArray.
731 
732 This class implements the interface of both MultiArray and
733 MultiArrayView. By default, MultiArrayViews are tagged as
734 unstrided. If necessary, strided arrays are constructed automatically
735 by calls to a variant of the bind...() function.
736 
737 In addition to the member functions described here, <tt>MultiArrayView</tt>
738 and its subclasses support arithmetic and algebraic functions via the
739 module \ref MultiMathModule.
740 
741 If you want to apply an algorithm requiring an image to a
742 <tt>MultiArrayView</tt> of appropriate (2-dimensional) shape, you can
743 create a \ref vigra::BasicImageView that acts as a wrapper with the
744 necessary interface -- see \ref MultiArrayToImage.
745 
746 The template parameter are as follows
747 \code
748  N: the array dimension
749 
750  T: the type of the array elements
751 
752  C: a tag determining whether the array's inner dimension is strided
753  or not. An array is unstrided if the array elements occupy consecutive
754  memory location, strided if there is an offset in between (e.g.
755  when a view is created that skips every other array element).
756  The compiler can generate faster code for unstrided arrays.
757  Possible values: UnstridedArrayTag (default), StridedArrayTag
758 \endcode
759 
760 <b>\#include</b>
761 <vigra/multi_array.hxx>
762 
763 Namespace: vigra
764 */
765 template <unsigned int N, class T, class StrideTag>
766 class MultiArrayView
767 {
768 public:
769 
770  /** the array's actual dimensionality.
771  This ensures that MultiArrayView can also be used for
772  scalars (that is, when <tt>N == 0</tt>). Calculated as:<br>
773  \code
774  actual_dimension = (N==0) ? 1 : N
775  \endcode
776  */
777  enum ActualDimension { actual_dimension = (N==0) ? 1 : N };
778 
779  /** the array's value type
780  */
781  typedef T value_type;
782 
783  /** reference type (result of operator[])
784  */
785  typedef value_type &reference;
786 
787  /** const reference type (result of operator[] const)
788  */
789  typedef const value_type &const_reference;
790 
791  /** pointer type
792  */
793  typedef value_type *pointer;
794 
795  /** const pointer type
796  */
797  typedef const value_type *const_pointer;
798 
799  /** difference type (used for multi-dimensional offsets and indices)
800  */
802 
803  /** size type
804  */
805  typedef difference_type size_type;
806 
807  /** difference and index type for a single dimension
808  */
810 
811  /** scan-order iterator (StridedScanOrderIterator) type
812  */
814 
815  /** const scan-order iterator (StridedScanOrderIterator) type
816  */
818 
819  /** traverser (MultiIterator) type
820  */
821  typedef typename vigra::detail::MultiIteratorChooser <
822  StrideTag>::template Traverser <actual_dimension, T, T &, T *>::type traverser;
823 
824  /** const traverser (MultiIterator) type
825  */
826  typedef typename vigra::detail::MultiIteratorChooser <
827  StrideTag>::template Traverser <actual_dimension, T, T const &, T const *>::type const_traverser;
828 
829  /** the view type associated with this array.
830  */
832 
833  /** the matrix type associated with this array.
834  */
836 
837 protected:
838 
839  typedef typename difference_type::value_type diff_zero_t;
840 
841  /** the shape of the image pointed to is stored here.
842  */
843  difference_type m_shape;
844 
845  /** the strides (offset of a sample to the next) for every dimension
846  are stored here.
847  */
848  difference_type m_stride;
849 
850  /** pointer to the image.
851  */
852  pointer m_ptr;
853 
854  template <class U, class CN>
855  void copyImpl(const MultiArrayView <N, U, CN>& rhs);
856 
857  template <class U, class CN>
858  void swapDataImpl(MultiArrayView <N, U, CN> rhs);
859 
860  template <class CN>
861  bool arraysOverlap(const MultiArrayView <N, T, CN>& rhs) const;
862 
863  template <class U, class CN>
864  bool arraysOverlap(const MultiArrayView <N, U, CN>&) const
865  {
866  return false;
867  }
868 
869  bool checkInnerStride(UnstridedArrayTag)
870  {
871  return m_stride[0] <= 1;
872  }
873 
874  bool checkInnerStride(StridedArrayTag)
875  {
876  return true;
877  }
878 
879 public:
880 
881  /** default constructor: create an invalid view,
882  * i.e. hasData() returns false and size() is zero.
883  */
885  : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0)
886  {}
887 
888  /** construct from shape and pointer
889  */
890  MultiArrayView (const difference_type &shape, pointer ptr)
891  : m_shape (shape),
892  m_stride (detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape)),
893  m_ptr (ptr)
894  {}
895 
896  /** Construct from shape, strides (offset of a sample to the
897  next) for every dimension, and pointer. (Note that
898  strides are not given in bytes, but in offset steps of the
899  respective pointer type.)
900  */
901  MultiArrayView (const difference_type &shape,
902  const difference_type &stride,
903  pointer ptr)
904  : m_shape (shape),
905  m_stride (stride),
906  m_ptr (ptr)
907  {
908  vigra_precondition(checkInnerStride(StrideTag()),
909  "MultiArrayView<..., UnstridedArrayTag>::MultiArrayView(): First dimension of given array is not unstrided.");
910  }
911 
912  /** Conversion to a strided view.
913  */
915  {
917  }
918 
919  /** Assignment. There are 3 cases:
920 
921  <ul>
922  <li> When this <tt>MultiArrayView</tt> does not point to valid data
923  (e.g. after default construction), it becomes a copy of \a rhs.
924  <li> When the shapes of the two arrays match, the array contents are copied.
925  <li> Otherwise, a <tt>PreconditionViolation</tt> exception is thrown.
926  </ul>
927  */
928  MultiArrayView & operator=(MultiArrayView const & rhs);
929 
930  /** Assignment of a differently typed MultiArrayView. Fails with
931  <tt>PreconditionViolation</tt> exception when the shapes do not match.
932  */
933  template<class U, class C1>
935  {
936  vigra_precondition(this->shape() == rhs.shape(),
937  "MultiArrayView::operator=() size mismatch.");
938  this->copyImpl(rhs);
939  return *this;
940  }
941 
942  /** Assignment of a scalar. Equivalent to MultiArrayView::init(v).
943  */
944  MultiArrayView & operator=(value_type const & v)
945  {
946  return init(v);
947  }
948 
949  /** Add-assignment of a compatible MultiArrayView. Fails with
950  <tt>PreconditionViolation</tt> exception when the shapes do not match.
951  */
952  template<class U, class C1>
954 
955  /** Subtract-assignment of a compatible MultiArrayView. Fails with
956  <tt>PreconditionViolation</tt> exception when the shapes do not match.
957  */
958  template<class U, class C1>
960 
961  /** Multiply-assignment of a compatible MultiArrayView. Fails with
962  <tt>PreconditionViolation</tt> exception when the shapes do not match.
963  */
964  template<class U, class C1>
966 
967  /** Divide-assignment of a compatible MultiArrayView. Fails with
968  <tt>PreconditionViolation</tt> exception when the shapes do not match.
969  */
970  template<class U, class C1>
972 
973  /** Add-assignment of a scalar.
974  */
975  MultiArrayView & operator+=(T const & rhs)
976  {
977  detail::copyAddScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
978  return *this;
979  }
980 
981  /** Subtract-assignment of a scalar.
982  */
983  MultiArrayView & operator-=(T const & rhs)
984  {
985  detail::copySubScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
986  return *this;
987  }
988 
989  /** Multiply-assignment of a scalar.
990  */
991  MultiArrayView & operator*=(T const & rhs)
992  {
993  detail::copyMulScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
994  return *this;
995  }
996 
997  /** Divide-assignment of a scalar.
998  */
999  MultiArrayView & operator/=(T const & rhs)
1000  {
1001  detail::copyDivScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
1002  return *this;
1003  }
1004 
1005  /** Assignment of an array expression. Fails with
1006  <tt>PreconditionViolation</tt> exception when the shapes do not match.
1007  */
1008  template<class Expression>
1009  MultiArrayView & operator=(multi_math::MultiMathOperand<Expression> const & rhs)
1010  {
1011  multi_math::detail::assign(*this, rhs);
1012  return *this;
1013  }
1014 
1015  /** Add-assignment of an array expression. Fails with
1016  <tt>PreconditionViolation</tt> exception when the shapes do not match.
1017  */
1018  template<class Expression>
1019  MultiArrayView & operator+=(multi_math::MultiMathOperand<Expression> const & rhs)
1020  {
1021  multi_math::detail::plusAssign(*this, rhs);
1022  return *this;
1023  }
1024 
1025  /** Subtract-assignment of an array expression. Fails with
1026  <tt>PreconditionViolation</tt> exception when the shapes do not match.
1027  */
1028  template<class Expression>
1029  MultiArrayView & operator-=(multi_math::MultiMathOperand<Expression> const & rhs)
1030  {
1031  multi_math::detail::minusAssign(*this, rhs);
1032  return *this;
1033  }
1034 
1035  /** Multiply-assignment of an array expression. Fails with
1036  <tt>PreconditionViolation</tt> exception when the shapes do not match.
1037  */
1038  template<class Expression>
1039  MultiArrayView & operator*=(multi_math::MultiMathOperand<Expression> const & rhs)
1040  {
1041  multi_math::detail::multiplyAssign(*this, rhs);
1042  return *this;
1043  }
1044 
1045  /** Divide-assignment of an array expression. Fails with
1046  <tt>PreconditionViolation</tt> exception when the shapes do not match.
1047  */
1048  template<class Expression>
1049  MultiArrayView & operator/=(multi_math::MultiMathOperand<Expression> const & rhs)
1050  {
1051  multi_math::detail::divideAssign(*this, rhs);
1052  return *this;
1053  }
1054 
1055  /** array access.
1056  */
1057  reference operator[] (const difference_type &d)
1058  {
1059  VIGRA_ASSERT_INSIDE(d);
1060  return m_ptr [dot (d, m_stride)];
1061  }
1062 
1063  /** array access.
1064  */
1065  const_reference operator[] (const difference_type &d) const
1066  {
1067  VIGRA_ASSERT_INSIDE(d);
1068  return m_ptr [dot (d, m_stride)];
1069  }
1070 
1071  /** equivalent to bindInner(), when M < N.
1072  */
1073  template <int M>
1075  {
1076  return bindInner(d);
1077  }
1078 
1079  /** Array access in scan-order sense.
1080  Mostly useful to support standard indexing for 1-dimensional multi-arrays,
1081  but works for any N. Use scanOrderIndexToCoordinate() and
1082  coordinateToScanOrderIndex() for conversion between indices and coordinates.
1083 
1084  <b>Note:</b> This function should not be used in the inner loop, because the
1085  conversion of the scan order index into a memory address is expensive
1086  (it must take into account that memory may not be consecutive for subarrays
1087  and/or strided arrays). Always prefer operator() if possible.
1088  */
1089  reference operator[](difference_type_1 d)
1090  {
1091  VIGRA_ASSERT_INSIDE(scanOrderIndexToCoordinate(d));
1092  return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
1093  }
1094 
1095  /** Array access in scan-order sense.
1096  Mostly useful to support standard indexing for 1-dimensional multi-arrays,
1097  but works for any N. Use scanOrderIndexToCoordinate() and
1098  coordinateToScanOrderIndex() for conversion between indices and coordinates.
1099 
1100  <b>Note:</b> This function should not be used in the inner loop, because the
1101  conversion of the scan order index into a memory address is expensive
1102  (it must take into account that memory may not be consecutive for subarrays
1103  and/or strided arrays). Always prefer operator() if possible.
1104  */
1105  const_reference operator[](difference_type_1 d) const
1106  {
1107  VIGRA_ASSERT_INSIDE(scanOrderIndexToCoordinate(d));
1108  return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
1109  }
1110 
1111  /** convert scan-order index to coordinate.
1112  */
1113  difference_type scanOrderIndexToCoordinate(difference_type_1 d) const
1114  {
1115  difference_type result;
1116  detail::ScanOrderToCoordinate<actual_dimension>::exec(d, m_shape, result);
1117  return result;
1118  }
1119 
1120  /** convert coordinate to scan-order index.
1121  */
1122  difference_type_1 coordinateToScanOrderIndex(const difference_type &d) const
1123  {
1124  return detail::CoordinateToScanOrder<actual_dimension>::exec(m_shape, d);
1125  }
1126 
1127  /** 1D array access. Use only if N == 1.
1128  */
1129  reference operator() (difference_type_1 x)
1130  {
1131  VIGRA_ASSERT_INSIDE(difference_type(x));
1132  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x)];
1133  }
1134 
1135  /** 2D array access. Use only if N == 2.
1136  */
1137  reference operator() (difference_type_1 x, difference_type_1 y)
1138  {
1139  VIGRA_ASSERT_INSIDE(difference_type(x, y));
1140  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x, y)];
1141  }
1142 
1143  /** 3D array access. Use only if N == 3.
1144  */
1145  reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z)
1146  {
1147  VIGRA_ASSERT_INSIDE(difference_type(x, y, z));
1148  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
1149  }
1150 
1151  /** 4D array access. Use only if N == 4.
1152  */
1153  reference operator() (difference_type_1 x, difference_type_1 y,
1154  difference_type_1 z, difference_type_1 u)
1155  {
1156  VIGRA_ASSERT_INSIDE(difference_type(x, y, z, u));
1157  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
1158  }
1159 
1160  /** 5D array access. Use only if N == 5.
1161  */
1162  reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z,
1163  difference_type_1 u, difference_type_1 v)
1164  {
1165  VIGRA_ASSERT_INSIDE(difference_type(x, y,z, u,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];
1167  }
1168 
1169  /** 1D const array access. Use only if N == 1.
1170  */
1171  const_reference operator() (difference_type_1 x) const
1172  {
1173  VIGRA_ASSERT_INSIDE(difference_type(x));
1174  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x)];
1175  }
1176 
1177  /** 2D const array access. Use only if N == 2.
1178  */
1179  const_reference operator() (difference_type_1 x, difference_type_1 y) const
1180  {
1181  VIGRA_ASSERT_INSIDE(difference_type(x, y));
1182  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x, y)];
1183  }
1184 
1185  /** 3D const array access. Use only if N == 3.
1186  */
1187  const_reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z) const
1188  {
1189  VIGRA_ASSERT_INSIDE(difference_type(x,y,z));
1190  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
1191  }
1192 
1193  /** 4D const array access. Use only if N == 4.
1194  */
1195  const_reference operator() (difference_type_1 x, difference_type_1 y,
1196  difference_type_1 z, difference_type_1 u) const
1197  {
1198  VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u));
1199  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
1200  }
1201 
1202  /** 5D const array access. Use only if N == 5.
1203  */
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
1206  {
1207  VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v));
1208  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
1209  }
1210 
1211  /** Init with a constant.
1212  */
1213  template <class U>
1214  MultiArrayView & init(const U & init)
1215  {
1216  if(hasData())
1217  detail::copyScalarMultiArrayData(traverser_begin(), shape(), init, MetaInt<actual_dimension-1>());
1218  return *this;
1219  }
1220 
1221 
1222  /** Copy the data of the right-hand array (array shapes must match).
1223  */
1224  void copy(const MultiArrayView & rhs)
1225  {
1226  if(this == &rhs)
1227  return;
1228  this->copyImpl(rhs);
1229  }
1230 
1231  /** Copy the data of the right-hand array (array shapes must match).
1232  */
1233  template <class U, class CN>
1235  {
1236  this->copyImpl(rhs);
1237  }
1238 
1239  /** swap the data between two MultiArrayView objects.
1240 
1241  The shapes of the two array must match.
1242  */
1244  {
1245  if(this != &rhs)
1246  swapDataImpl(rhs);
1247  }
1248 
1249  /** swap the data between two MultiArrayView objects.
1250 
1251  The shapes of the two array must match.
1252  */
1253  template <class T2, class C2>
1255  {
1256  swapDataImpl(rhs);
1257  }
1258 
1259  /** check whether the array is unstrided (i.e. has consecutive memory) up
1260  to the given dimension.
1261 
1262  \a dimension can range from 0 ... N-1. If a certain dimension is unstrided,
1263  all lower dimensions are also unstrided.
1264  */
1265  bool isUnstrided(unsigned int dimension = N-1) const
1266  {
1267  difference_type s = vigra::detail::defaultStride<actual_dimension>(shape());
1268  for(unsigned int k = 0; k <= dimension; ++k)
1269  if(stride(k) != s[k])
1270  return false;
1271  return true;
1272  }
1273 
1274  /** bind the M outmost dimensions to certain indices.
1275  this reduces the dimensionality of the image to
1276  max { 1, N-M }.
1277 
1278  <b>Usage:</b>
1279  \code
1280  // create a 3D array of size 40x30x20
1281  typedef MultiArray<3, double>::difference_type Shape;
1282  MultiArray<3, double> array3(Shape(40, 30, 20));
1283 
1284  // get a 1D array by fixing index 1 to 12, and index 2 to 10
1285  MultiArrayView <1, double> array1 = array3.bindOuter(TinyVector<MultiArrayIndex, 2>(12, 10));
1286  \endcode
1287  */
1288  template <int M, class Index>
1289  MultiArrayView <N-M, T, StrideTag> bindOuter(const TinyVector <Index, M> &d) const;
1290 
1291  /** bind the M innermost dimensions to certain indices.
1292  this reduces the dimensionality of the image to
1293  max { 1, N-M }.
1294 
1295  <b>Usage:</b>
1296  \code
1297  // create a 3D array of size 40x30x20
1298  typedef MultiArray<3, double>::difference_type Shape;
1299  MultiArray<3, double> array3(Shape(40, 30, 20));
1300 
1301  // get a 1D array by fixing index 0 to 12, and index 1 to 10
1302  MultiArrayView <1, double, StridedArrayTag> array1 = array3.bindInner(TinyVector<MultiArrayIndex, 2>(12, 10));
1303  \endcode
1304  */
1305  template <int M, class Index>
1307 
1308  /** bind dimension M to index d.
1309  this reduces the dimensionality of the image to
1310  max { 1, N-1 }.
1311 
1312  <b>Usage:</b>
1313  \code
1314  // create a 3D array of size 40x30x20
1315  typedef MultiArray<3, double>::difference_type Shape;
1316  MultiArray<3, double> array3(Shape(40, 30, 20));
1317 
1318  // get a 2D array by fixing index 1 to 12
1319  MultiArrayView <2, double> array2 = array3.bind<1>(12);
1320 
1321  // get a 2D array by fixing index 0 to 23
1322  MultiArrayView <2, double, StridedArrayTag> array2a = array3.bind<0>(23);
1323  \endcode
1324  */
1325  template <unsigned int M>
1326  MultiArrayView <N-1, T, typename vigra::detail::MaybeStrided<StrideTag, M>::type >
1327  bind (difference_type_1 d) const;
1328 
1329  /** bind the outmost dimension to a certain index.
1330  this reduces the dimensionality of the image to
1331  max { 1, N-1 }.
1332 
1333  <b>Usage:</b>
1334  \code
1335  // create a 3D array of size 40x30x20
1336  typedef MultiArray<3, double>::difference_type Shape;
1337  MultiArray<3, double> array3(Shape(40, 30, 20));
1338 
1339  // get a 2D array by fixing the outermost index (i.e. index 2) to 12
1340  MultiArrayView <2, double> array2 = array3.bindOuter(12);
1341  \endcode
1342  */
1343  MultiArrayView <N-1, T, StrideTag> bindOuter (difference_type_1 d) const;
1344 
1345  /** bind the innermost dimension to a certain index.
1346  this reduces the dimensionality of the image to
1347  max { 1, N-1 }.
1348 
1349  <b>Usage:</b>
1350  \code
1351  // create a 3D array of size 40x30x20
1352  typedef MultiArray<3, double>::difference_type Shape;
1353  MultiArray<3, double> array3(Shape(40, 30, 20));
1354 
1355  // get a 2D array by fixing the innermost index (i.e. index 0) to 23
1356  MultiArrayView <2, double, StridedArrayTag> array2 = array3.bindInner(23);
1357  \endcode
1358  */
1359  MultiArrayView <N-1, T, StridedArrayTag> bindInner (difference_type_1 d) const;
1360 
1361  /** bind dimension m to index d.
1362  this reduces the dimensionality of the image to
1363  max { 1, N-1 }.
1364 
1365  <b>Usage:</b>
1366  \code
1367  // create a 3D array of size 40x30x20
1368  typedef MultiArray<3, double>::difference_type Shape;
1369  MultiArray<3, double> array3(Shape(40, 30, 20));
1370 
1371  // get a 2D array by fixing index 2 to 15
1372  MultiArrayView <2, double, StridedArrayTag> array2 = array3.bindAt(2, 15);
1373  \endcode
1374  */
1376  bindAt (difference_type_1 m, difference_type_1 d) const;
1377 
1378 
1379  /** Create a view to channel 'i' of a vector-like value type. Possible value types
1380  (of the original array) are: \ref TinyVector, \ref RGBValue, \ref FFTWComplex,
1381  and <tt>std::complex</tt>. The list can be extended to any type whose memory
1382  layout is equivalent to a fixed-size C array, by specializing
1383  <tt>ExpandElementResult</tt>.
1384 
1385  <b>Usage:</b>
1386  \code
1387  MultiArray<2, RGBValue<float> > rgb_image(Shape2(w, h));
1388 
1389  MultiArrayView<2, float, StridedArrayTag> red = rgb_image.bindElementChannel(0);
1390  MultiArrayView<2, float, StridedArrayTag> green = rgb_image.bindElementChannel(1);
1391  MultiArrayView<2, float, StridedArrayTag> blue = rgb_image.bindElementChannel(2);
1392  \endcode
1393  */
1395  bindElementChannel(difference_type_1 i) const
1396  {
1397  vigra_precondition(0 <= i && i < ExpandElementResult<T>::size,
1398  "MultiArrayView::bindElementChannel(i): 'i' out of range.");
1399  return expandElements(0).bindInner(i);
1400  }
1401 
1402  /** Create a view where a vector-like element type is expanded into a new
1403  array dimension. The new dimension is inserted at index position 'd',
1404  which must be between 0 and N inclusive.
1405 
1406  Possible value types of the original array are: \ref TinyVector, \ref RGBValue,
1407  \ref FFTWComplex, <tt>std::complex</tt>, and the built-in number types (in this
1408  case, <tt>expandElements</tt> is equivalent to <tt>insertSingletonDimension</tt>).
1409  The list of supported types can be extended to any type whose memory
1410  layout is equivalent to a fixed-size C array, by specializing
1411  <tt>ExpandElementResult</tt>.
1412 
1413  <b>Usage:</b>
1414  \code
1415  MultiArray<2, RGBValue<float> > rgb_image(Shape2(w, h));
1416 
1417  MultiArrayView<3, float, StridedArrayTag> multiband_image = rgb_image.expandElements(2);
1418  \endcode
1419  */
1421  expandElements(difference_type_1 d) const;
1422 
1423  /** Add a singleton dimension (dimension of length 1).
1424 
1425  Singleton dimensions don't change the size of the data, but introduce
1426  a new index that can only take the value 0. This is mainly useful for
1427  the 'reduce mode' of transformMultiArray() and combineTwoMultiArrays(),
1428  because these functions require the source and destination arrays to
1429  have the same number of dimensions.
1430 
1431  The range of \a i must be <tt>0 <= i <= N</tt>. The new dimension will become
1432  the i'th index, and the old indices from i upwards will shift one
1433  place to the right.
1434 
1435  <b>Usage:</b>
1436 
1437  Suppose we want have a 2D array and want to create a 1D array that contains
1438  the row average of the first array.
1439  \code
1440  typedef MultiArrayShape<2>::type Shape2;
1441  MultiArray<2, double> original(Shape2(40, 30));
1442 
1443  typedef MultiArrayShape<1>::type Shape1;
1444  MultiArray<1, double> rowAverages(Shape1(30));
1445 
1446  // temporarily add a singleton dimension to the destination array
1447  transformMultiArray(srcMultiArrayRange(original),
1448  destMultiArrayRange(rowAverages.insertSingletonDimension(0)),
1449  FindAverage<double>());
1450  \endcode
1451  */
1453  insertSingletonDimension (difference_type_1 i) const;
1454 
1455  /** Create a view to the diagonal elements of the array.
1456 
1457  This produces a 1D array view whose size equals the size
1458  of the shortest dimension of the original array.
1459 
1460  <b>Usage:</b>
1461  \code
1462  // create a 3D array of size 40x30x20
1463  typedef MultiArray<3, double>::difference_type Shape;
1464  MultiArray<3, double> array3(Shape(40, 30, 20));
1465 
1466  // get a view to the diagonal elements
1467  MultiArrayView <1, double, StridedArrayTag> diagonal = array3.diagonal();
1468  assert(diagonal.shape(0) == 20);
1469  \endcode
1470  */
1472  {
1474  Shape1(vigra::sum(m_stride)), m_ptr);
1475  }
1476 
1477  /** create a rectangular subarray that spans between the
1478  points p and q, where p is in the subarray, q not.
1479 
1480  <b>Usage:</b>
1481  \code
1482  // create a 3D array of size 40x30x20
1483  typedef MultiArray<3, double>::difference_type Shape;
1484  MultiArray<3, double> array3(Shape(40, 30, 20));
1485 
1486  // get a subarray set is smaller by one element at all sides
1487  MultiArrayView <3, double> subarray = array3.subarray(Shape(1,1,1), Shape(39, 29, 19));
1488  \endcode
1489  */
1490  MultiArrayView subarray (const difference_type &p,
1491  const difference_type &q) const
1492  {
1493  const difference_type_1 offset = dot (m_stride, p);
1494  return MultiArrayView (q - p, m_stride, m_ptr + offset);
1495  }
1496 
1497  /** apply an additional striding to the image, thereby reducing
1498  the shape of the array.
1499  for example, multiplying the stride of dimension one by three
1500  turns an appropriately laid out (interleaved) rgb image into
1501  a single band image.
1502  */
1504  stridearray (const difference_type &s) const
1505  {
1506  difference_type shape = m_shape;
1507  for (unsigned int i = 0; i < actual_dimension; ++i)
1508  shape [i] /= s [i];
1509  return MultiArrayView <N, T, StridedArrayTag>(shape, m_stride * s, m_ptr);
1510  }
1511 
1512  /** Transpose an array. If N==2, this implements the usual matrix transposition.
1513  For N > 2, it reverses the order of the indices.
1514 
1515  <b>Usage:</b><br>
1516  \code
1517  typedef MultiArray<2, double>::difference_type Shape;
1518  MultiArray<2, double> array(10, 20);
1519 
1520  MultiArray<2, double, StridedArrayTag> transposed = array.transpose();
1521 
1522  for(int i=0; i<array.shape(0), ++i)
1523  for(int j=0; j<array.shape(1); ++j)
1524  assert(array(i, j) == transposed(j, i));
1525  \endcode
1526  */
1528  transpose () const
1529  {
1530  difference_type shape(m_shape.begin(), difference_type::ReverseCopy),
1531  stride(m_stride.begin(), difference_type::ReverseCopy);
1533  }
1534 
1535  /** permute the dimensions of the array.
1536  The function exchanges the meaning of the dimensions without copying the data.
1537  In case of a 2-dimensional array, this is simply array transposition. In higher dimensions,
1538  there are more possibilities.
1539 
1540  <b>Usage:</b><br>
1541  \code
1542  typedef MultiArray<2, double>::difference_type Shape;
1543  MultiArray<2, double> array(10, 20);
1544 
1545  MultiArray<2, double, StridedArrayTag> transposed = array.permuteDimensions(Shape(1,0));
1546 
1547  for(int i=0; i<array.shape(0), ++i)
1548  for(int j=0; j<array.shape(1); ++j)
1549  assert(array(i, j) == transposed(j, i));
1550  \endcode
1551  */
1553  permuteDimensions (const difference_type &s) const;
1554 
1555  /** Permute the dimensions of the array so that the strides are in ascending order.
1556  Determines the appropriate permutation and then calls permuteDimensions().
1557  */
1559  permuteStridesAscending() const;
1560 
1561  /** Permute the dimensions of the array so that the strides are in descending order.
1562  Determines the appropriate permutation and then calls permuteDimensions().
1563  */
1565  permuteStridesDescending() const;
1566 
1567  /** Compute the ordering of the strides in this array.
1568  The result is describes the current permutation of the axes relative
1569  to the standard ascending stride order.
1570  */
1571  difference_type strideOrdering() const
1572  {
1573  return strideOrdering(m_stride);
1574  }
1575 
1576  /** Compute the ordering of the given strides.
1577  The result is describes the current permutation of the axes relative
1578  to the standard ascending stride order.
1579  */
1580  static difference_type strideOrdering(difference_type strides);
1581 
1582  /** number of the elements in the array.
1583  */
1584  difference_type_1 elementCount () const
1585  {
1586  difference_type_1 ret = m_shape[0];
1587  for(int i = 1; i < actual_dimension; ++i)
1588  ret *= m_shape[i];
1589  return ret;
1590  }
1591 
1592  /** number of the elements in the array.
1593  Same as <tt>elementCount()</tt>. Mostly useful to support the std::vector interface.
1594  */
1595  difference_type_1 size () const
1596  {
1597  return elementCount();
1598  }
1599 
1600  /** return the array's shape.
1601  */
1602  const difference_type & shape () const
1603  {
1604  return m_shape;
1605  }
1606 
1607  /** return the array's size at a certain dimension.
1608  */
1609  difference_type_1 size (difference_type_1 n) const
1610  {
1611  return m_shape [n];
1612  }
1613 
1614  /** return the array's shape at a certain dimension
1615  (same as <tt>size(n)</tt>).
1616  */
1617  difference_type_1 shape (difference_type_1 n) const
1618  {
1619  return m_shape [n];
1620  }
1621 
1622  /** return the array's stride for every dimension.
1623  */
1624  const difference_type & stride () const
1625  {
1626  return m_stride;
1627  }
1628 
1629  /** return the array's stride at a certain dimension.
1630  */
1631  difference_type_1 stride (int n) const
1632  {
1633  return m_stride [n];
1634  }
1635 
1636  /** check whether two arrays are elementwise equal.
1637  */
1638  template <class U, class C1>
1639  bool operator==(MultiArrayView<N, U, C1> const & rhs) const
1640  {
1641  if(this->shape() != rhs.shape())
1642  return false;
1643  return detail::equalityOfMultiArrays(traverser_begin(), shape(), rhs.traverser_begin(), MetaInt<actual_dimension-1>());
1644  }
1645 
1646  /** check whether two arrays are not elementwise equal.
1647  Also true when the two arrays have different shapes.
1648  */
1649  template <class U, class C1>
1650  bool operator!=(MultiArrayView<N, U, C1> const & rhs) const
1651  {
1652  return !operator==(rhs);
1653  }
1654 
1655  /** check whether the given point is in the array range.
1656  */
1657  bool isInside (difference_type const & p) const
1658  {
1659  for(int d=0; d<actual_dimension; ++d)
1660  if(p[d] < 0 || p[d] >= shape(d))
1661  return false;
1662  return true;
1663  }
1664 
1665  /** Check if the array contains only non-zero elements (or if all elements
1666  are 'true' if the value type is 'bool').
1667  */
1668  bool all() const
1669  {
1670  bool res = true;
1671  detail::reduceOverMultiArray(traverser_begin(), shape(),
1672  res,
1673  detail::AllTrueReduceFunctor(),
1674  MetaInt<actual_dimension-1>());
1675  return res;
1676  }
1677 
1678  /** Check if the array contains a non-zero element (or an element
1679  that is 'true' if the value type is 'bool').
1680  */
1681  bool any() const
1682  {
1683  bool res = false;
1684  detail::reduceOverMultiArray(traverser_begin(), shape(),
1685  res,
1686  detail::AnyTrueReduceFunctor(),
1687  MetaInt<actual_dimension-1>());
1688  return res;
1689  }
1690 
1691  /** Find the minimum and maximum element in this array.
1692  See \ref FeatureAccumulators for a general feature
1693  extraction framework.
1694  */
1695  void minmax(T * minimum, T * maximum) const
1696  {
1697  std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min());
1698  detail::reduceOverMultiArray(traverser_begin(), shape(),
1699  res,
1700  detail::MinmaxReduceFunctor(),
1701  MetaInt<actual_dimension-1>());
1702  *minimum = res.first;
1703  *maximum = res.second;
1704  }
1705 
1706  /** Compute the mean and variance of the values in this array.
1707  See \ref FeatureAccumulators for a general feature
1708  extraction framework.
1709  */
1710  template <class U>
1711  void meanVariance(U * mean, U * variance) const
1712  {
1713  typedef typename NumericTraits<U>::RealPromote R;
1714  R zero = R();
1715  triple<double, R, R> res(0.0, zero, zero);
1716  detail::reduceOverMultiArray(traverser_begin(), shape(),
1717  res,
1718  detail::MeanVarianceReduceFunctor(),
1719  MetaInt<actual_dimension-1>());
1720  *mean = res.second;
1721  *variance = res.third / res.first;
1722  }
1723 
1724  /** Compute the sum of the array elements.
1725 
1726  You must provide the type of the result by an explicit template parameter:
1727  \code
1728  MultiArray<2, UInt8> A(width, height);
1729 
1730  double sum = A.sum<double>();
1731  \endcode
1732  */
1733  template <class U>
1734  U sum() const
1735  {
1736  U res = NumericTraits<U>::zero();
1737  detail::reduceOverMultiArray(traverser_begin(), shape(),
1738  res,
1739  detail::SumReduceFunctor(),
1740  MetaInt<actual_dimension-1>());
1741  return res;
1742  }
1743 
1744  /** Compute the sum of the array elements over selected axes.
1745 
1746  \arg sums must have the same shape as this array, except for the
1747  axes along which the sum is to be accumulated. These axes must be
1748  singletons. Note that you must include <tt>multi_pointoperators.hxx</tt>
1749  for this function to work.
1750 
1751  <b>Usage:</b>
1752  \code
1753  #include <vigra/multi_array.hxx>
1754  #include <vigra/multi_pointoperators.hxx>
1755 
1756  MultiArray<2, double> A(rows, cols);
1757  ... // fill A
1758 
1759  // make the first axis a singleton to sum over the first index
1760  MultiArray<2, double> rowSums(1, cols);
1761  A.sum(rowSums);
1762 
1763  // this is equivalent to
1764  transformMultiArray(srcMultiArrayRange(A),
1765  destMultiArrayRange(rowSums),
1766  FindSum<double>());
1767  \endcode
1768  */
1769  template <class U, class S>
1770  void sum(MultiArrayView<N, U, S> sums) const
1771  {
1772  transformMultiArray(srcMultiArrayRange(*this),
1773  destMultiArrayRange(sums),
1774  FindSum<U>());
1775  }
1776 
1777  /** Compute the product of the array elements.
1778 
1779  You must provide the type of the result by an explicit template parameter:
1780  \code
1781  MultiArray<2, UInt8> A(width, height);
1782 
1783  double prod = A.product<double>();
1784  \endcode
1785  */
1786  template <class U>
1787  U product() const
1788  {
1789  U res = NumericTraits<U>::one();
1790  detail::reduceOverMultiArray(traverser_begin(), shape(),
1791  res,
1792  detail::ProdReduceFunctor(),
1793  MetaInt<actual_dimension-1>());
1794  return res;
1795  }
1796 
1797  /** Compute the squared Euclidean norm of the array (sum of squares of the array elements).
1798  */
1799  typename NormTraits<MultiArrayView>::SquaredNormType
1800  squaredNorm() const
1801  {
1802  typedef typename NormTraits<MultiArrayView>::SquaredNormType SquaredNormType;
1803  SquaredNormType res = NumericTraits<SquaredNormType>::zero();
1804  detail::reduceOverMultiArray(traverser_begin(), shape(),
1805  res,
1806  detail::SquaredL2NormReduceFunctor(),
1807  MetaInt<actual_dimension-1>());
1808  return res;
1809  }
1810 
1811  /** Compute various norms of the array.
1812  The norm is determined by parameter \a type:
1813 
1814  <ul>
1815  <li> type == 0: maximum norm (L-infinity): maximum of absolute values of the array elements
1816  <li> type == 1: Manhattan norm (L1): sum of absolute values of the array elements
1817  <li> type == 2: Euclidean norm (L2): square root of <tt>squaredNorm()</tt> when \a useSquaredNorm is <tt>true</tt>,<br>
1818  or direct algorithm that avoids underflow/overflow otherwise.
1819  </ul>
1820 
1821  Parameter \a useSquaredNorm has no effect when \a type != 2. Defaults: compute L2 norm as square root of
1822  <tt>squaredNorm()</tt>.
1823  */
1824  typename NormTraits<MultiArrayView>::NormType
1825  norm(int type = 2, bool useSquaredNorm = true) const;
1826 
1827  /** return the pointer to the image data
1828  */
1829  pointer data () const
1830  {
1831  return m_ptr;
1832  }
1833 
1834  pointer & unsafePtr()
1835  {
1836  return m_ptr;
1837  }
1838 
1839  /**
1840  * returns true iff this view refers to valid data,
1841  * i.e. data() is not a NULL pointer. (this is false after
1842  * default construction.)
1843  */
1844  bool hasData () const
1845  {
1846  return m_ptr != 0;
1847  }
1848 
1849  /** returns a scan-order iterator pointing
1850  to the first array element.
1851  */
1852  iterator begin()
1853  {
1854  return iterator(m_ptr, m_shape, m_stride);
1855  }
1856 
1857  /** returns a const scan-order iterator pointing
1858  to the first array element.
1859  */
1860  const_iterator begin() const
1861  {
1862  return const_iterator(m_ptr, m_shape, m_stride);
1863  }
1864 
1865  /** returns a scan-order iterator pointing
1866  beyond the last array element.
1867  */
1868  iterator end()
1869  {
1870  return begin().getEndIterator();
1871  }
1872 
1873  /** returns a const scan-order iterator pointing
1874  beyond the last array element.
1875  */
1876  const_iterator end() const
1877  {
1878  return begin().getEndIterator();
1879  }
1880 
1881  /** returns the N-dimensional MultiIterator pointing
1882  to the first element in every dimension.
1883  */
1884  traverser traverser_begin ()
1885  {
1886  traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1887  return ret;
1888  }
1889 
1890  /** returns the N-dimensional MultiIterator pointing
1891  to the const first element in every dimension.
1892  */
1893  const_traverser traverser_begin () const
1894  {
1895  const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1896  return ret;
1897  }
1898 
1899  /** returns the N-dimensional MultiIterator pointing
1900  beyond the last element in dimension N, and to the
1901  first element in every other dimension.
1902  */
1903  traverser traverser_end ()
1904  {
1905  traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1906  ret += m_shape [actual_dimension-1];
1907  return ret;
1908  }
1909 
1910  /** returns the N-dimensional const MultiIterator pointing
1911  beyond the last element in dimension N, and to the
1912  first element in every other dimension.
1913  */
1914  const_traverser traverser_end () const
1915  {
1916  const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1917  ret += m_shape [actual_dimension-1];
1918  return ret;
1919  }
1920 
1921  view_type view ()
1922  {
1923  return *this;
1924  }
1925 };
1926 
1927 template <unsigned int N, class T, class StrideTag>
1928 MultiArrayView<N, T, StrideTag> &
1930 {
1931  if(this == &rhs)
1932  return *this;
1933  vigra_precondition(this->shape() == rhs.shape() || m_ptr == 0,
1934  "MultiArrayView::operator=(MultiArrayView const &) size mismatch.");
1935  if(m_ptr == 0)
1936  {
1937  m_shape = rhs.m_shape;
1938  m_stride = rhs.m_stride;
1939  m_ptr = rhs.m_ptr;
1940  }
1941  else
1942  this->copyImpl(rhs);
1943  return *this;
1944 }
1945 
1946 template <unsigned int N, class T, class StrideTag>
1947 template <class CN>
1948 bool
1950 {
1951  vigra_precondition (shape () == rhs.shape (),
1952  "MultiArrayView::arraysOverlap(): shape mismatch.");
1953  const_pointer first_element = this->m_ptr,
1954  last_element = first_element + dot(this->m_shape - difference_type(1), this->m_stride);
1956  rhs_first_element = rhs.data(),
1957  rhs_last_element = rhs_first_element + dot(rhs.shape() - difference_type(1), rhs.stride());
1958  return !(last_element < rhs_first_element || rhs_last_element < first_element);
1959 }
1960 
1961 template <unsigned int N, class T, class StrideTag>
1962 template <class U, class CN>
1963 void
1964 MultiArrayView <N, T, StrideTag>::copyImpl(const MultiArrayView <N, U, CN>& rhs)
1965 {
1966  if(!arraysOverlap(rhs))
1967  {
1968  // no overlap -- can copy directly
1969  detail::copyMultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>());
1970  }
1971  else
1972  {
1973  // overlap: we got different views to the same data -- copy to intermediate memory in order to avoid
1974  // overwriting elements that are still needed on the rhs.
1975  MultiArray<N, T> tmp(rhs);
1976  detail::copyMultiArrayData(tmp.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>());
1977  }
1978 }
1979 
1980 #define VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(name, op) \
1981 template <unsigned int N, class T, class StrideTag> \
1982 template<class U, class C1> \
1983 MultiArrayView<N, T, StrideTag> & \
1984 MultiArrayView <N, T, StrideTag>::operator op(MultiArrayView<N, U, C1> const & rhs) \
1985 { \
1986  vigra_precondition(this->shape() == rhs.shape(), "MultiArrayView::operator" #op "() size mismatch."); \
1987  if(!arraysOverlap(rhs)) \
1988  { \
1989  detail::name##MultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>()); \
1990  } \
1991  else \
1992  { \
1993  MultiArray<N, T> tmp(rhs); \
1994  detail::name##MultiArrayData(tmp.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>()); \
1995  } \
1996  return *this; \
1997 }
1998 
1999 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyAdd, +=)
2000 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copySub, -=)
2001 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyMul, *=)
2002 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyDiv, /=)
2003 
2004 #undef VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT
2005 
2006 template <unsigned int N, class T, class StrideTag>
2007 template <class U, class CN>
2008 void
2009 MultiArrayView <N, T, StrideTag>::swapDataImpl(MultiArrayView <N, U, CN> rhs)
2010 {
2011  vigra_precondition (shape () == rhs.shape (),
2012  "MultiArrayView::swapData(): shape mismatch.");
2013 
2014  // check for overlap of this and rhs
2015  const_pointer first_element = this->m_ptr,
2016  last_element = first_element + dot(this->m_shape - difference_type(1), this->m_stride);
2017  typename MultiArrayView <N, U, CN>::const_pointer
2018  rhs_first_element = rhs.data(),
2019  rhs_last_element = rhs_first_element + dot(rhs.shape() - difference_type(1), rhs.stride());
2020  if(last_element < rhs_first_element || rhs_last_element < first_element)
2021  {
2022  // no overlap -- can swap directly
2023  detail::swapDataImpl(traverser_begin(), shape(), rhs.traverser_begin(), MetaInt<actual_dimension-1>());
2024  }
2025  else
2026  {
2027  // overlap: we got different views to the same data -- copy to intermediate memory in order to avoid
2028  // overwriting elements that are still needed.
2029  MultiArray<N, T> tmp(*this);
2030  copy(rhs);
2031  rhs.copy(tmp);
2032  }
2033 }
2034 
2035 template <unsigned int N, class T, class StrideTag>
2036 MultiArrayView <N, T, StridedArrayTag>
2038 {
2039  difference_type shape, stride, check((typename difference_type::value_type)0);
2040  for (unsigned int i = 0; i < actual_dimension; ++i)
2041  {
2042  shape[i] = m_shape[s[i]];
2043  stride[i] = m_stride[s[i]];
2044  ++check[s[i]];
2045  }
2046  vigra_precondition(check == difference_type(1),
2047  "MultiArrayView::permuteDimensions(): every dimension must occur exactly once.");
2049 }
2050 
2051 template <unsigned int N, class T, class StrideTag>
2054 {
2055  difference_type permutation;
2056  for(int k=0; k<(int)N; ++k)
2057  permutation[k] = k;
2058  for(int k=0; k<(int)N-1; ++k)
2059  {
2060  int smallest = k;
2061  for(int j=k+1; j<(int)N; ++j)
2062  {
2063  if(stride[j] < stride[smallest])
2064  smallest = j;
2065  }
2066  if(smallest != k)
2067  {
2068  std::swap(stride[k], stride[smallest]);
2069  std::swap(permutation[k], permutation[smallest]);
2070  }
2071  }
2072  difference_type ordering;
2073  for(unsigned int k=0; k<N; ++k)
2074  ordering[permutation[k]] = k;
2075  return ordering;
2076 }
2077 
2078 template <unsigned int N, class T, class StrideTag>
2081 {
2082  difference_type ordering(strideOrdering(m_stride)), permutation;
2083  for(MultiArrayIndex k=0; k<N; ++k)
2084  permutation[ordering[k]] = k;
2085  return permuteDimensions(permutation);
2086 }
2087 
2088 template <unsigned int N, class T, class StrideTag>
2091 {
2092  difference_type ordering(strideOrdering(m_stride)), permutation;
2093  for(MultiArrayIndex k=0; k<N; ++k)
2094  permutation[N-1-ordering[k]] = k;
2095  return permuteDimensions(permutation);
2096 }
2097 
2098 template <unsigned int N, class T, class StrideTag>
2099 template <int M, class Index>
2100 MultiArrayView <N-M, T, StrideTag>
2102 {
2104  stride.init (m_stride.begin () + N-M, m_stride.end ());
2105  pointer ptr = m_ptr + dot (d, stride);
2106  static const int NNew = (N-M == 0) ? 1 : N-M;
2107  TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride;
2108  if (N-M == 0)
2109  {
2110  inner_shape [0] = 1;
2111  inner_stride [0] = 0;
2112  }
2113  else
2114  {
2115  inner_shape.init (m_shape.begin (), m_shape.end () - M);
2116  inner_stride.init (m_stride.begin (), m_stride.end () - M);
2117  }
2118  return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, ptr);
2119 }
2120 
2121 template <unsigned int N, class T, class StrideTag>
2122 template <int M, class Index>
2123 MultiArrayView <N - M, T, StridedArrayTag>
2125 {
2127  stride.init (m_stride.begin (), m_stride.end () - N + M);
2128  pointer ptr = m_ptr + dot (d, stride);
2129  static const int NNew = (N-M == 0) ? 1 : N-M;
2130  TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride;
2131  if (N-M == 0)
2132  {
2133  outer_shape [0] = 1;
2134  outer_stride [0] = 0;
2135  }
2136  else
2137  {
2138  outer_shape.init (m_shape.begin () + M, m_shape.end ());
2139  outer_stride.init (m_stride.begin () + M, m_stride.end ());
2140  }
2141  return MultiArrayView <N-M, T, StridedArrayTag>
2142  (outer_shape, outer_stride, ptr);
2143 }
2144 
2145 template <unsigned int N, class T, class StrideTag>
2146 template <unsigned int M>
2147 MultiArrayView <N-1, T, typename detail::MaybeStrided<StrideTag, M>::type >
2149 {
2150  static const int NNew = (N-1 == 0) ? 1 : N-1;
2152  // the remaining dimensions are 0..n-1,n+1..N-1
2153  if (N-1 == 0)
2154  {
2155  shape[0] = 1;
2156  stride[0] = 0;
2157  }
2158  else
2159  {
2160  std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ());
2161  std::copy (m_shape.begin () + M+1, m_shape.end (),
2162  shape.begin () + M);
2163  std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin ());
2164  std::copy (m_stride.begin () + M+1, m_stride.end (),
2165  stride.begin () + M);
2166  }
2167  return MultiArrayView <N-1, T, typename detail::MaybeStrided<StrideTag, M>::type>
2168  (shape, stride, m_ptr + d * m_stride[M]);
2169 }
2170 
2171 template <unsigned int N, class T, class StrideTag>
2172 MultiArrayView <N - 1, T, StrideTag>
2174 {
2175  static const int NNew = (N-1 == 0) ? 1 : N-1;
2176  TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride;
2177  if (N-1 == 0)
2178  {
2179  inner_shape [0] = 1;
2180  inner_stride [0] = 0;
2181  }
2182  else
2183  {
2184  inner_shape.init (m_shape.begin (), m_shape.end () - 1);
2185  inner_stride.init (m_stride.begin (), m_stride.end () - 1);
2186  }
2187  return MultiArrayView <N-1, T, StrideTag> (inner_shape, inner_stride,
2188  m_ptr + d * m_stride [N-1]);
2189 }
2190 
2191 template <unsigned int N, class T, class StrideTag>
2192 MultiArrayView <N - 1, T, StridedArrayTag>
2194 {
2195  static const int NNew = (N-1 == 0) ? 1 : N-1;
2196  TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride;
2197  if (N-1 == 0)
2198  {
2199  outer_shape [0] = 1;
2200  outer_stride [0] = 0;
2201  }
2202  else
2203  {
2204  outer_shape.init (m_shape.begin () + 1, m_shape.end ());
2205  outer_stride.init (m_stride.begin () + 1, m_stride.end ());
2206  }
2207  return MultiArrayView <N-1, T, StridedArrayTag>
2208  (outer_shape, outer_stride, m_ptr + d * m_stride [0]);
2209 }
2210 
2211 template <unsigned int N, class T, class StrideTag>
2212 MultiArrayView <N - 1, T, StridedArrayTag>
2214 {
2215  vigra_precondition (
2216  n < static_cast <int> (N),
2217  "MultiArrayView <N, T, StrideTag>::bindAt(): dimension out of range.");
2218  static const int NNew = (N-1 == 0) ? 1 : N-1;
2220  // the remaining dimensions are 0..n-1,n+1..N-1
2221  if (N-1 == 0)
2222  {
2223  shape [0] = 1;
2224  stride [0] = 0;
2225  }
2226  else
2227  {
2228  std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ());
2229  std::copy (m_shape.begin () + n+1, m_shape.end (),
2230  shape.begin () + n);
2231  std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ());
2232  std::copy (m_stride.begin () + n+1, m_stride.end (),
2233  stride.begin () + n);
2234  }
2235  return MultiArrayView <N-1, T, StridedArrayTag>
2236  (shape, stride, m_ptr + d * m_stride[n]);
2237 }
2238 
2239 
2240 template <unsigned int N, class T, class StrideTag>
2243 {
2244  vigra_precondition(0 <= d && d <= static_cast <difference_type_1> (N),
2245  "MultiArrayView<N, ...>::expandElements(d): 0 <= 'd' <= N required.");
2246 
2247  int elementSize = ExpandElementResult<T>::size;
2248  typename MultiArrayShape<N+1>::type newShape, newStrides;
2249  for(int k=0; k<d; ++k)
2250  {
2251  newShape[k] = m_shape[k];
2252  newStrides[k] = m_stride[k]*elementSize;
2253  }
2254 
2255  newShape[d] = elementSize;
2256  newStrides[d] = 1;
2257 
2258  for(int k=d; k<N; ++k)
2259  {
2260  newShape[k+1] = m_shape[k];
2261  newStrides[k+1] = m_stride[k]*elementSize;
2262  }
2263 
2264  typedef typename ExpandElementResult<T>::type U;
2266  newShape, newStrides, reinterpret_cast<U*>(m_ptr));
2267 }
2268 
2269 template <unsigned int N, class T, class StrideTag>
2272 {
2273  vigra_precondition (
2274  0 <= i && i <= static_cast <difference_type_1> (N),
2275  "MultiArrayView <N, T, StrideTag>::insertSingletonDimension(): index out of range.");
2277  std::copy (m_shape.begin (), m_shape.begin () + i, shape.begin ());
2278  std::copy (m_shape.begin () + i, m_shape.end (), shape.begin () + i + 1);
2279  std::copy (m_stride.begin (), m_stride.begin () + i, stride.begin ());
2280  std::copy (m_stride.begin () + i, m_stride.end (), stride.begin () + i + 1);
2281  shape[i] = 1;
2282  stride[i] = 1;
2283 
2285 }
2286 
2287 template <unsigned int N, class T, class StrideTag>
2288 typename NormTraits<MultiArrayView <N, T, StrideTag> >::NormType
2289 MultiArrayView <N, T, StrideTag>::norm(int type, bool useSquaredNorm) const
2290 {
2291  typedef typename NormTraits<MultiArrayView>::NormType NormType;
2292 
2293  switch(type)
2294  {
2295  case 0:
2296  {
2297  NormType res = NumericTraits<NormType>::zero();
2298  detail::reduceOverMultiArray(traverser_begin(), shape(),
2299  res,
2300  detail::MaxNormReduceFunctor(),
2301  MetaInt<actual_dimension-1>());
2302  return res;
2303  }
2304  case 1:
2305  {
2306  NormType res = NumericTraits<NormType>::zero();
2307  detail::reduceOverMultiArray(traverser_begin(), shape(),
2308  res,
2309  detail::L1NormReduceFunctor(),
2310  MetaInt<actual_dimension-1>());
2311  return res;
2312  }
2313  case 2:
2314  {
2315  if(useSquaredNorm)
2316  {
2317  return sqrt((NormType)squaredNorm());
2318  }
2319  else
2320  {
2321  NormType normMax = NumericTraits<NormType>::zero();
2322  detail::reduceOverMultiArray(traverser_begin(), shape(),
2323  normMax,
2324  detail::MaxNormReduceFunctor(),
2325  MetaInt<actual_dimension-1>());
2326  if(normMax == NumericTraits<NormType>::zero())
2327  return normMax;
2328  NormType res = NumericTraits<NormType>::zero();
2329  detail::reduceOverMultiArray(traverser_begin(), shape(),
2330  res,
2331  detail::WeightedL2NormReduceFunctor<NormType>(1.0/normMax),
2332  MetaInt<actual_dimension-1>());
2333  return sqrt(res)*normMax;
2334  }
2335  }
2336  default:
2337  vigra_precondition(false, "MultiArrayView::norm(): Unknown norm type.");
2338  return NumericTraits<NormType>::zero(); // unreachable
2339  }
2340 }
2341 
2342 
2343 /********************************************************/
2344 /* */
2345 /* norm */
2346 /* */
2347 /********************************************************/
2348 
2349 template <unsigned int N, class T, class StrideTag>
2350 inline typename NormTraits<MultiArrayView <N, T, StrideTag> >::SquaredNormType
2352 {
2353  return a.squaredNorm();
2354 }
2355 
2356 template <unsigned int N, class T, class StrideTag>
2357 inline typename NormTraits<MultiArrayView <N, T, StrideTag> >::NormType
2358 norm(MultiArrayView <N, T, StrideTag> const & a)
2359 {
2360  return a.norm();
2361 }
2362 
2363 /********************************************************/
2364 /* */
2365 /* MultiArray */
2366 /* */
2367 /********************************************************/
2368 
2369 /** \brief Main <TT>MultiArray</TT> class containing the memory
2370  management.
2371 
2372 This class inherits the interface of MultiArrayView, and implements
2373 the memory ownership.
2374 MultiArray's are always unstrided, striding them creates a MultiArrayView.
2375 
2376 
2377 The template parameters are as follows
2378 \code
2379  N: the array dimension
2380 
2381  T: the type of the array elements
2382 
2383  A: the allocator used for internal storage management
2384  (default: std::allocator<T>)
2385 \endcode
2386 
2387 <b>\#include</b>
2388 <vigra/multi_array.hxx>
2389 
2390 Namespace: vigra
2391 */
2392 template <unsigned int N, class T, class A /* default already declared above */>
2393 class MultiArray : public MultiArrayView <N, T>
2394 {
2395 
2396 public:
2397  using MultiArrayView <N, T>::actual_dimension;
2398 
2399  /** the allocator type used to allocate the memory
2400  */
2401  typedef A allocator_type;
2402 
2403  /** the view type associated with this array.
2404  */
2406 
2407  /** the matrix type associated with this array.
2408  */
2410 
2411  /** the array's value type
2412  */
2414 
2415  /** pointer type
2416  */
2417  typedef typename view_type::pointer pointer;
2418 
2419  /** const pointer type
2420  */
2422 
2423  /** reference type (result of operator[])
2424  */
2426 
2427  /** const reference type (result of operator[] const)
2428  */
2430 
2431  /** size type
2432  */
2434 
2435  /** difference type (used for multi-dimensional offsets and indices)
2436  */
2438 
2439  /** difference and index type for a single dimension
2440  */
2442 
2443  /** traverser type
2444  */
2445  typedef typename vigra::detail::MultiIteratorChooser <
2446  UnstridedArrayTag>::template Traverser <N, T, T &, T *>::type
2448 
2449  /** traverser type to const data
2450  */
2451  typedef typename vigra::detail::MultiIteratorChooser <
2452  UnstridedArrayTag>::template Traverser <N, T, T const &, T const *>::type
2454 
2455  /** sequential (random access) iterator type
2456  */
2457  typedef T * iterator;
2458 
2459  /** sequential (random access) const iterator type
2460  */
2461  typedef T * const_iterator;
2462 
2463 protected:
2464 
2465  typedef typename difference_type::value_type diff_zero_t;
2466 
2467  /** the allocator used to allocate the memory
2468  */
2470 
2471  /** allocate memory for s pixels, write its address into the given
2472  pointer and initialize the pixels with init.
2473  */
2474  void allocate (pointer &ptr, difference_type_1 s, const_reference init);
2475 
2476  /** allocate memory for s pixels, write its address into the given
2477  pointer and initialize the linearized pixels to the values of init.
2478  */
2479  template <class U>
2480  void allocate (pointer &ptr, difference_type_1 s, U const * init);
2481 
2482  /** allocate memory, write its address into the given
2483  pointer and initialize it by copying the data from the given MultiArrayView.
2484  */
2485  template <class U, class StrideTag>
2486  void allocate (pointer &ptr, MultiArrayView<N, U, StrideTag> const & init);
2487 
2488  /** deallocate the memory (of length s) starting at the given address.
2489  */
2490  void deallocate (pointer &ptr, difference_type_1 s);
2491 
2492  template <class U, class StrideTag>
2493  void copyOrReshape (const MultiArrayView<N, U, StrideTag> &rhs);
2494 public:
2495  /** default constructor
2496  */
2498  : MultiArrayView <N, T> (difference_type (diff_zero_t(0)),
2499  difference_type (diff_zero_t(0)), 0)
2500  {}
2501 
2502  /** construct with given allocator
2503  */
2504  MultiArray (allocator_type const & alloc)
2505  : MultiArrayView <N, T> (difference_type (diff_zero_t(0)),
2506  difference_type (diff_zero_t(0)), 0),
2507  m_alloc(alloc)
2508  {}
2509 
2510  /** construct with given length
2511 
2512  Use only for 1-dimensional arrays (<tt>N==1</tt>).
2513  */
2514  explicit MultiArray (difference_type_1 length,
2515  allocator_type const & alloc = allocator_type());
2516 
2517  /** construct with given shape
2518  */
2519  explicit MultiArray (const difference_type &shape,
2520  allocator_type const & alloc = allocator_type());
2521 
2522  /** construct from shape with an initial value
2523  */
2524  MultiArray (const difference_type &shape, const_reference init,
2525  allocator_type const & alloc = allocator_type());
2526 
2527  /** construct from shape and copy values from the given array
2528  */
2529  MultiArray (const difference_type &shape, const_pointer init,
2530  allocator_type const & alloc = allocator_type());
2531 
2532  /** copy constructor
2533  */
2534  MultiArray (const MultiArray &rhs)
2535  : MultiArrayView <N, T> (rhs.m_shape, rhs.m_stride, 0),
2536  m_alloc (rhs.m_alloc)
2537  {
2538  allocate (this->m_ptr, this->elementCount (), rhs.data ());
2539  }
2540 
2541  /** constructor from an array expression
2542  */
2543  template<class Expression>
2544  MultiArray (multi_math::MultiMathOperand<Expression> const & rhs,
2545  allocator_type const & alloc = allocator_type())
2546  : MultiArrayView <N, T> (difference_type (diff_zero_t(0)),
2547  difference_type (diff_zero_t(0)), 0),
2548  m_alloc (alloc)
2549  {
2550  multi_math::detail::assignOrResize(*this, rhs);
2551  }
2552 
2553  /** construct by copying from a MultiArrayView
2554  */
2555  template <class U, class StrideTag>
2557  allocator_type const & alloc = allocator_type());
2558 
2559  /** assignment.<br>
2560  If the size of \a rhs is the same as the left-hand side arrays's old size, only
2561  the data are copied. Otherwise, new storage is allocated, which invalidates all
2562  objects (array views, iterators) depending on the lhs array.
2563  */
2565  {
2566  if (this != &rhs)
2567  this->copyOrReshape(rhs);
2568  return *this;
2569  }
2570 
2571  /** assignment from arbitrary MultiArrayView.<br>
2572  If the size of \a rhs is the same as the left-hand side arrays's old size, only
2573  the data are copied. Otherwise, new storage is allocated, which invalidates all
2574  objects (array views, iterators) depending on the lhs array.
2575  */
2576  template <class U, class StrideTag>
2578  {
2579  this->copyOrReshape(rhs);
2580  return *this;
2581  }
2582 
2583  /** assignment from scalar.<br>
2584  Equivalent to MultiArray::init(v).
2585  */
2587  {
2588  return this->init(v);
2589  }
2590 
2591  /** Add-assignment from arbitrary MultiArrayView. Fails with
2592  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2593  If the left array has no data (hasData() is false), this function is
2594  equivalent to a normal assignment (i.e. an empty
2595  array is interpreted as a zero-array of appropriate size).
2596  */
2597  template <class U, class StrideTag>
2599  {
2600  if(this->hasData())
2601  view_type::operator+=(rhs);
2602  else
2603  *this = rhs;
2604  return *this;
2605  }
2606 
2607  /** Subtract-assignment from arbitrary MultiArrayView. Fails with
2608  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2609  If the left array has no data (hasData() is false), this function is
2610  equivalent to an assignment of the negated rhs (i.e. an empty
2611  array is interpreted as a zero-array of appropriate size).
2612  */
2613  template <class U, class StrideTag>
2615  {
2616  if(!this->hasData())
2617  this->reshape(rhs.shape());
2618  view_type::operator-=(rhs);
2619  return *this;
2620  }
2621 
2622  /** Multiply-assignment from arbitrary MultiArrayView. Fails with
2623  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2624  If the left array has no data (hasData() is false), this function is
2625  equivalent to reshape(rhs.shape()) with zero initialisation (i.e. an empty
2626  array is interpreted as a zero-array of appropriate size).
2627  */
2628  template <class U, class StrideTag>
2630  {
2631  if(this->hasData())
2632  view_type::operator*=(rhs);
2633  else
2634  this->reshape(rhs.shape());
2635  return *this;
2636  }
2637 
2638  /** Divide-assignment from arbitrary MultiArrayView. Fails with
2639  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2640  If the left array has no data (hasData() is false), this function is
2641  equivalent to reshape(rhs.shape()) with zero initialisation (i.e. an empty
2642  array is interpreted as a zero-array of appropriate size).
2643  */
2644  template <class U, class StrideTag>
2646  {
2647  if(this->hasData())
2648  view_type::operator/=(rhs);
2649  else
2650  this->reshape(rhs.shape());
2651  return *this;
2652  }
2653 
2654  /** Add-assignment of a scalar.
2655  */
2656  MultiArray &operator+= (const T &rhs)
2657  {
2658  view_type::operator+=(rhs);
2659  return *this;
2660  }
2661 
2662  /** Subtract-assignment of a scalar.
2663  */
2664  MultiArray &operator-= (const T &rhs)
2665  {
2666  view_type::operator-=(rhs);
2667  return *this;
2668  }
2669 
2670  /** Multiply-assignment of a scalar.
2671  */
2672  MultiArray &operator*= (const T &rhs)
2673  {
2674  view_type::operator*=(rhs);
2675  return *this;
2676  }
2677 
2678  /** Divide-assignment of a scalar.
2679  */
2680  MultiArray &operator/= (const T &rhs)
2681  {
2682  view_type::operator/=(rhs);
2683  return *this;
2684  }
2685  /** Assignment of an array expression. Fails with
2686  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2687  */
2688  template<class Expression>
2689  MultiArray & operator=(multi_math::MultiMathOperand<Expression> const & rhs)
2690  {
2691  multi_math::detail::assignOrResize(*this, rhs);
2692  return *this;
2693  }
2694 
2695  /** Add-assignment of an array expression. Fails with
2696  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2697  */
2698  template<class Expression>
2699  MultiArray & operator+=(multi_math::MultiMathOperand<Expression> const & rhs)
2700  {
2701  multi_math::detail::plusAssignOrResize(*this, rhs);
2702  return *this;
2703  }
2704 
2705  /** Subtract-assignment of an array expression. Fails with
2706  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2707  */
2708  template<class Expression>
2709  MultiArray & operator-=(multi_math::MultiMathOperand<Expression> const & rhs)
2710  {
2711  multi_math::detail::minusAssignOrResize(*this, rhs);
2712  return *this;
2713  }
2714 
2715  /** Multiply-assignment of an array expression. Fails with
2716  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2717  */
2718  template<class Expression>
2719  MultiArray & operator*=(multi_math::MultiMathOperand<Expression> const & rhs)
2720  {
2721  multi_math::detail::multiplyAssignOrResize(*this, rhs);
2722  return *this;
2723  }
2724 
2725  /** Divide-assignment of an array expression. Fails with
2726  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2727  */
2728  template<class Expression>
2729  MultiArray & operator/=(multi_math::MultiMathOperand<Expression> const & rhs)
2730  {
2731  multi_math::detail::divideAssignOrResize(*this, rhs);
2732  return *this;
2733  }
2734 
2735  /** destructor
2736  */
2738  {
2739  deallocate (this->m_ptr, this->elementCount ());
2740  }
2741 
2742 
2743  /** init elements with a constant
2744  */
2745  template <class U>
2746  MultiArray & init(const U & init)
2747  {
2748  view_type::init(init);
2749  return *this;
2750  }
2751 
2752  /** Allocate new memory with the given shape and initialize with zeros.<br>
2753  <em>Note:</em> this operation invalidates all dependent objects
2754  (array views and iterators)
2755  */
2756  void reshape (const difference_type &shape)
2757  {
2758  reshape (shape, T());
2759  }
2760 
2761  /** Allocate new memory with the given shape and initialize it
2762  with the given value.<br>
2763  <em>Note:</em> this operation invalidates all dependent objects
2764  (array views and iterators)
2765  */
2766  void reshape (const difference_type &shape, const_reference init);
2767 
2768  /** Swap the contents with another MultiArray. This is fast,
2769  because no data are copied, but only pointers and shapes swapped.
2770  <em>Note:</em> this operation invalidates all dependent objects
2771  (array views and iterators)
2772  */
2773  void swap (MultiArray & other);
2774 
2775  /** sequential iterator pointing to the first array element.
2776  */
2778  {
2779  return this->data();
2780  }
2781 
2782  /** sequential iterator pointing beyond the last array element.
2783  */
2785  {
2786  return this->data() + this->elementCount();
2787  }
2788 
2789  /** sequential const iterator pointing to the first array element.
2790  */
2792  {
2793  return this->data();
2794  }
2795 
2796  /** sequential const iterator pointing beyond the last array element.
2797  */
2799  {
2800  return this->data() + this->elementCount();
2801  }
2802 
2803  /** get the allocator.
2804  */
2805  allocator_type const & allocator () const
2806  {
2807  return m_alloc;
2808  }
2809 };
2810 
2811 template <unsigned int N, class T, class A>
2813  allocator_type const & alloc)
2815  detail::defaultStride <1> (difference_type(length)),
2816  0),
2817  m_alloc(alloc)
2818 {
2819  allocate (this->m_ptr, this->elementCount (), T());
2820 }
2821 
2822 template <unsigned int N, class T, class A>
2824  allocator_type const & alloc)
2825 : MultiArrayView <N, T> (shape,
2826  detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape),
2827  0),
2828  m_alloc(alloc)
2829 {
2830  if (N == 0)
2831  {
2832  this->m_shape [0] = 1;
2833  this->m_stride [0] = 0;
2834  }
2835  allocate (this->m_ptr, this->elementCount (), T());
2836 }
2837 
2838 template <unsigned int N, class T, class A>
2840  allocator_type const & alloc)
2841 : MultiArrayView <N, T> (shape,
2842  detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape),
2843  0),
2844  m_alloc(alloc)
2845 {
2846  if (N == 0)
2847  {
2848  this->m_shape [0] = 1;
2849  this->m_stride [0] = 0;
2850  }
2851  allocate (this->m_ptr, this->elementCount (), init);
2852 }
2853 
2854 template <unsigned int N, class T, class A>
2856  allocator_type const & alloc)
2857 : MultiArrayView <N, T> (shape,
2858  detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (shape),
2859  0),
2860  m_alloc(alloc)
2861 {
2862  if (N == 0)
2863  {
2864  this->m_shape [0] = 1;
2865  this->m_stride [0] = 0;
2866  }
2867  allocate (this->m_ptr, this->elementCount (), init);
2868 }
2869 
2870 template <unsigned int N, class T, class A>
2871 template <class U, class StrideTag>
2873  allocator_type const & alloc)
2874 : MultiArrayView <N, T> (rhs.shape(),
2875  detail::defaultStride <MultiArrayView<N,T>::actual_dimension>(rhs.shape()),
2876  0),
2877  m_alloc (alloc)
2878 {
2879  allocate (this->m_ptr, rhs);
2880 }
2881 
2882 template <unsigned int N, class T, class A>
2883 template <class U, class StrideTag>
2884 void
2886 {
2887  if (this->shape() == rhs.shape())
2888  this->copy(rhs);
2889  else
2890  {
2891  MultiArray t(rhs);
2892  this->swap(t);
2893  }
2894 }
2895 
2896 template <unsigned int N, class T, class A>
2898  const_reference initial)
2899 {
2900  if (N== 0)
2901  {
2902  return;
2903  }
2904  else if(new_shape == this->shape())
2905  {
2906  this->init(initial);
2907  }
2908  else
2909  {
2910  difference_type new_stride = detail::defaultStride <MultiArrayView<N,T>::actual_dimension> (new_shape);
2912  T *new_ptr;
2913  allocate (new_ptr, new_size, initial);
2914  deallocate (this->m_ptr, this->elementCount ());
2915  this->m_ptr = new_ptr;
2916  this->m_shape = new_shape;
2917  this->m_stride = new_stride;
2918  }
2919 }
2920 
2921 
2922 template <unsigned int N, class T, class A>
2923 inline void
2925 {
2926  if (this == &other)
2927  return;
2928  std::swap(this->m_shape, other.m_shape);
2929  std::swap(this->m_stride, other.m_stride);
2930  std::swap(this->m_ptr, other.m_ptr);
2931  std::swap(this->m_alloc, other.m_alloc);
2932 }
2933 
2934 template <unsigned int N, class T, class A>
2937 {
2938  ptr = m_alloc.allocate ((typename A::size_type)s);
2940  try {
2941  for (i = 0; i < s; ++i)
2942  m_alloc.construct (ptr + i, init);
2943  }
2944  catch (...) {
2945  for (difference_type_1 j = 0; j < i; ++j)
2946  m_alloc.destroy (ptr + j);
2947  m_alloc.deallocate (ptr, (typename A::size_type)s);
2948  throw;
2949  }
2950 }
2951 
2952 template <unsigned int N, class T, class A>
2953 template <class U>
2955  U const * init)
2956 {
2957  ptr = m_alloc.allocate ((typename A::size_type)s);
2959  try {
2960  for (i = 0; i < s; ++i, ++init)
2961  m_alloc.construct (ptr + i, *init);
2962  }
2963  catch (...) {
2964  for (difference_type_1 j = 0; j < i; ++j)
2965  m_alloc.destroy (ptr + j);
2966  m_alloc.deallocate (ptr, (typename A::size_type)s);
2967  throw;
2968  }
2969 }
2970 
2971 template <unsigned int N, class T, class A>
2972 template <class U, class StrideTag>
2974 {
2975  difference_type_1 s = init.elementCount();
2976  ptr = m_alloc.allocate ((typename A::size_type)s);
2977  pointer p = ptr;
2978  try {
2979  detail::uninitializedCopyMultiArrayData(init.traverser_begin(), init.shape(),
2980  p, m_alloc, MetaInt<actual_dimension-1>());
2981  }
2982  catch (...) {
2983  for (pointer pp = ptr; pp < p; ++pp)
2984  m_alloc.destroy (pp);
2985  m_alloc.deallocate (ptr, (typename A::size_type)s);
2986  throw;
2987  }
2988 }
2989 
2990 template <unsigned int N, class T, class A>
2992 {
2993  if (ptr == 0)
2994  return;
2995  for (difference_type_1 i = 0; i < s; ++i)
2996  m_alloc.destroy (ptr + i);
2997  m_alloc.deallocate (ptr, (typename A::size_type)s);
2998  ptr = 0;
2999 }
3000 
3001 /********************************************************/
3002 /* */
3003 /* argument object factories */
3004 /* */
3005 /********************************************************/
3006 
3007 template <unsigned int N, class T, class StrideTag>
3008 inline triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3011 srcMultiArrayRange( MultiArrayView<N,T,StrideTag> const & array )
3012 {
3013  return triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3016  ( array.traverser_begin(),
3017  array.shape(),
3019 }
3020 
3021 template <unsigned int N, class T, class StrideTag, class Accessor>
3022 inline triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3023  typename MultiArrayView<N,T,StrideTag>::difference_type,
3024  Accessor >
3025 srcMultiArrayRange( MultiArrayView<N,T,StrideTag> const & array, Accessor a )
3026 {
3027  return triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3028  typename MultiArrayView<N,T,StrideTag>::difference_type,
3029  Accessor >
3030  ( array.traverser_begin(),
3031  array.shape(),
3032  a);
3033 }
3034 
3035 template <unsigned int N, class T, class StrideTag>
3036 inline pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3037  typename AccessorTraits<T>::default_const_accessor >
3038 srcMultiArray( MultiArrayView<N,T,StrideTag> const & array )
3039 {
3040  return pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3041  typename AccessorTraits<T>::default_const_accessor >
3042  ( array.traverser_begin(),
3043  typename AccessorTraits<T>::default_const_accessor() );
3044 }
3045 
3046 template <unsigned int N, class T, class StrideTag, class Accessor>
3047 inline pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3048  Accessor >
3049 srcMultiArray( MultiArrayView<N,T,StrideTag> const & array, Accessor a )
3050 {
3051  return pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3052  Accessor >
3053  ( array.traverser_begin(), a );
3054 }
3055 
3056 template <unsigned int N, class T, class StrideTag>
3057 inline triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3058  typename MultiArrayView<N,T,StrideTag>::difference_type,
3059  typename AccessorTraits<T>::default_accessor >
3060 destMultiArrayRange( MultiArrayView<N,T,StrideTag> & array )
3061 {
3062  return triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3063  typename MultiArrayView<N,T,StrideTag>::difference_type,
3064  typename AccessorTraits<T>::default_accessor >
3065  ( array.traverser_begin(),
3066  array.shape(),
3067  typename AccessorTraits<T>::default_accessor() );
3068 }
3069 
3070 template <unsigned int N, class T, class StrideTag, class Accessor>
3071 inline triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3072  typename MultiArrayView<N,T,StrideTag>::difference_type,
3073  Accessor >
3074 destMultiArrayRange( MultiArrayView<N,T,StrideTag> & array, Accessor a )
3075 {
3076  return triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3077  typename MultiArrayView<N,T,StrideTag>::difference_type,
3078  Accessor >
3079  ( array.traverser_begin(),
3080  array.shape(),
3081  a );
3082 }
3083 
3084 template <unsigned int N, class T, class StrideTag>
3085 inline pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3086  typename AccessorTraits<T>::default_accessor >
3087 destMultiArray( MultiArrayView<N,T,StrideTag> & array )
3088 {
3089  return pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3090  typename AccessorTraits<T>::default_accessor >
3091  ( array.traverser_begin(),
3092  typename AccessorTraits<T>::default_accessor() );
3093 }
3094 
3095 template <unsigned int N, class T, class StrideTag, class Accessor>
3096 inline pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3097  Accessor >
3098 destMultiArray( MultiArrayView<N,T,StrideTag> & array, Accessor a )
3099 {
3100  return pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3101  Accessor >
3102  ( array.traverser_begin(), a );
3103 }
3104 
3105 /********************************************************************/
3106 
3107 template <class PixelType, class Accessor>
3108 inline triple<ConstStridedImageIterator<PixelType>,
3109  ConstStridedImageIterator<PixelType>, Accessor>
3110 srcImageRange(const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3111 {
3112  ConstStridedImageIterator<PixelType>
3113  ul(img.data(), 1, img.stride(0), img.stride(1));
3114  return triple<ConstStridedImageIterator<PixelType>,
3115  ConstStridedImageIterator<PixelType>,
3116  Accessor>(
3117  ul, ul + Size2D(img.shape(0), img.shape(1)), a);
3118 }
3119 
3120 template <class PixelType, class Accessor>
3121 inline pair<ConstStridedImageIterator<PixelType>, Accessor>
3122 srcImage(const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3123 {
3124  ConstStridedImageIterator<PixelType>
3125  ul(img.data(), 1, img.stride(0), img.stride(1));
3126  return pair<ConstStridedImageIterator<PixelType>, Accessor>
3127  (ul, a);
3128 }
3129 
3130 template <class PixelType, class Accessor>
3131 inline triple<StridedImageIterator<PixelType>,
3132  StridedImageIterator<PixelType>, Accessor>
3133 destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3134 {
3135  StridedImageIterator<PixelType>
3136  ul(img.data(), 1, img.stride(0), img.stride(1));
3137  return triple<StridedImageIterator<PixelType>,
3138  StridedImageIterator<PixelType>,
3139  Accessor>(
3140  ul, ul + Size2D(img.shape(0), img.shape(1)), a);
3141 }
3142 
3143 template <class PixelType, class Accessor>
3144 inline pair<StridedImageIterator<PixelType>, Accessor>
3145 destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3146 {
3147  StridedImageIterator<PixelType>
3148  ul(img.data(), 1, img.stride(0), img.stride(1));
3149  return pair<StridedImageIterator<PixelType>, Accessor>
3150  (ul, a);
3151 }
3152 
3153 template <class PixelType, class Accessor>
3154 inline pair<StridedImageIterator<PixelType>, Accessor>
3155 maskImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3156 {
3157  StridedImageIterator<PixelType>
3158  ul(img.data(), 1, img.stride(0), img.stride(1));
3159  return pair<StridedImageIterator<PixelType>, Accessor>
3160  (ul, a);
3161 }
3162 
3163 // -------------------------------------------------------------------
3164 
3165 template <class PixelType>
3166 inline triple<ConstStridedImageIterator<PixelType>,
3167  ConstStridedImageIterator<PixelType>,
3168  typename AccessorTraits<PixelType>::default_const_accessor>
3169 srcImageRange(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
3170 {
3171  ConstStridedImageIterator<PixelType>
3172  ul(img.data(), 1, img.stride(0), img.stride(1));
3173  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3174  return triple<ConstStridedImageIterator<PixelType>,
3175  ConstStridedImageIterator<PixelType>,
3176  Accessor>
3177  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3178 }
3179 
3180 template <class PixelType>
3181 inline triple<ConstImageIterator<PixelType>,
3182  ConstImageIterator<PixelType>,
3183  typename AccessorTraits<PixelType>::default_const_accessor>
3184 srcImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
3185 {
3186  ConstImageIterator<PixelType>
3187  ul(img.data(), img.stride(1));
3188  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3189  return triple<ConstImageIterator<PixelType>,
3190  ConstImageIterator<PixelType>,
3191  Accessor>
3192  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3193 }
3194 
3195 template <class PixelType>
3196 inline pair< ConstStridedImageIterator<PixelType>,
3197  typename AccessorTraits<PixelType>::default_const_accessor>
3198 srcImage(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
3199 {
3200  ConstStridedImageIterator<PixelType>
3201  ul(img.data(), 1, img.stride(0), img.stride(1));
3202  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3203  return pair<ConstStridedImageIterator<PixelType>,
3204  Accessor>
3205  (ul, Accessor());
3206 }
3207 
3208 template <class PixelType>
3209 inline pair< ConstImageIterator<PixelType>,
3210  typename AccessorTraits<PixelType>::default_const_accessor>
3211 srcImage(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
3212 {
3213  ConstImageIterator<PixelType>
3214  ul(img.data(), img.stride(1));
3215  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3216  return pair<ConstImageIterator<PixelType>,
3217  Accessor>
3218  (ul, Accessor());
3219 }
3220 
3221 template <class PixelType>
3222 inline triple< StridedImageIterator<PixelType>,
3223  StridedImageIterator<PixelType>,
3224  typename AccessorTraits<PixelType>::default_accessor>
3225 destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img)
3226 {
3227  StridedImageIterator<PixelType>
3228  ul(img.data(), 1, img.stride(0), img.stride(1));
3229  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3230  return triple<StridedImageIterator<PixelType>,
3231  StridedImageIterator<PixelType>,
3232  Accessor>
3233  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3234 }
3235 
3236 template <class PixelType>
3237 inline triple< ImageIterator<PixelType>,
3238  ImageIterator<PixelType>,
3239  typename AccessorTraits<PixelType>::default_accessor>
3240 destImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag> & img)
3241 {
3242  ImageIterator<PixelType>
3243  ul(img.data(), img.stride(1));
3244  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3245  return triple<ImageIterator<PixelType>,
3246  ImageIterator<PixelType>,
3247  Accessor>
3248  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3249 }
3250 
3251 template <class PixelType>
3252 inline pair< StridedImageIterator<PixelType>,
3253  typename AccessorTraits<PixelType>::default_accessor>
3254 destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img)
3255 {
3256  StridedImageIterator<PixelType>
3257  ul(img.data(), 1, img.stride(0), img.stride(1));
3258  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3259  return pair<StridedImageIterator<PixelType>, Accessor>
3260  (ul, Accessor());
3261 }
3262 
3263 template <class PixelType>
3264 inline pair< ImageIterator<PixelType>,
3265  typename AccessorTraits<PixelType>::default_accessor>
3266 destImage(MultiArrayView<2, PixelType, UnstridedArrayTag> & img)
3267 {
3268  ImageIterator<PixelType> ul(img.data(), img.stride(1));
3269  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3270  return pair<ImageIterator<PixelType>, Accessor>(ul, Accessor());
3271 }
3272 
3273 template <class PixelType>
3274 inline pair< ConstStridedImageIterator<PixelType>,
3275  typename AccessorTraits<PixelType>::default_accessor>
3276 maskImage(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
3277 {
3278  ConstStridedImageIterator<PixelType>
3279  ul(img.data(), 1, img.stride(0), img.stride(1));
3280  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3281  return pair<ConstStridedImageIterator<PixelType>, Accessor>
3282  (ul, Accessor());
3283 }
3284 
3285 template <class PixelType>
3286 inline pair< ConstImageIterator<PixelType>,
3287  typename AccessorTraits<PixelType>::default_accessor>
3288 maskImage(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
3289 {
3290  ConstImageIterator<PixelType>
3291  ul(img.data(), img.stride(1));
3292  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3293  return pair<ConstImageIterator<PixelType>, Accessor>
3294  (ul, Accessor());
3295 }
3296 
3297 /********************************************************/
3298 /* */
3299 /* makeBasicImageView */
3300 /* */
3301 /********************************************************/
3302 
3303 /** \addtogroup MultiArrayToImage Wrap a \ref vigra::MultiArrayView in
3304  a \ref vigra::BasicImageView
3305 */
3306 //@{
3307 /** Create a \ref vigra::BasicImageView from an unstrided 2-dimensional
3308  \ref vigra::MultiArrayView.
3309 
3310  The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
3311  as the original \ref vigra::MultiArrayView.
3312 */
3313 template <class T>
3314 BasicImageView <T>
3316 {
3317  return BasicImageView <T> (array.data (), array.shape (0),
3318  array.shape (1));
3319 }
3320 
3321 /** Create a \ref vigra::BasicImageView from a 3-dimensional
3322  \ref vigra::MultiArray.
3323 
3324  This wrapper flattens the two innermost dimensions of the array
3325  into single rows of the resulting image.
3326  The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
3327  as the original \ref vigra::MultiArray.
3328 */
3329 template <class T>
3330 BasicImageView <T>
3332 {
3333  return BasicImageView <T> (array.data (),
3334  array.shape (0)*array.shape (1), array.shape (2));
3335 }
3336 
3337 /** Create a \ref vigra::BasicImageView from a 3-dimensional
3338  \ref vigra::MultiArray.
3339 
3340  This wrapper only works if <tt>T</tt> is a scalar type and the
3341  array's innermost dimension has size 3. It then re-interprets
3342  the data array as a 2-dimensional array with value_type
3343  <tt>RGBValue<T></tt>.
3344 */
3345 template <class T>
3346 BasicImageView <RGBValue<T> >
3348 {
3349  vigra_precondition (
3350  array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3.");
3351  return BasicImageView <RGBValue<T> > (
3352  reinterpret_cast <RGBValue <T> *> (array.data ()),
3353  array.shape (1), array.shape (2));
3354 }
3355 
3356 //@}
3357 
3358 } // namespace vigra
3359 
3360 #undef VIGRA_ASSERT_INSIDE
3361 
3362 #endif // VIGRA_MULTI_ARRAY_HXX
BasicImageView< RGBValue< T > > makeRGBImageView(MultiArray< 3, T > const &array)
Definition: multi_array.hxx:3347
MultiArray & operator/=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2729
const value_type & const_reference
Definition: multi_array.hxx:789
MultiArray & operator=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2689
void sum(MultiArrayView< N, U, S > sums) const
Definition: multi_array.hxx:1770
MultiArrayView & operator=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:1009
iterator end()
Definition: multi_array.hxx:1868
Sequential iterator for MultiArrayView.
Definition: multi_iterator.hxx:2079
MultiArrayView & operator*=(MultiArrayView< N, U, C1 > const &rhs)
MultiArrayView & operator+=(T const &rhs)
Definition: multi_array.hxx:975
MultiArray< N, T > matrix_type
Definition: multi_array.hxx:835
MultiArray< N, T, A > matrix_type
Definition: multi_array.hxx:2409
PromoteTraits< V1, V2 >::Promote dot(RGBValue< V1, RIDX1, GIDX1, BIDX1 > const &r1, RGBValue< V2, RIDX2, GIDX2, BIDX2 > const &r2)
dot product
Definition: rgbvalue.hxx:894
view_type::pointer pointer
Definition: multi_array.hxx:2417
MultiArrayShape< actual_dimension >::type difference_type
Definition: multi_array.hxx:801
MultiArrayView & operator=(value_type const &v)
Definition: multi_array.hxx:944
MultiArray & operator+=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2699
MultiArray()
Definition: multi_array.hxx:2497
vigra::detail::MultiIteratorChooser< UnstridedArrayTag >::template Traverser< N, T, T const &, T const * >::type const_traverser
Definition: multi_array.hxx:2453
MultiArrayView< N, T > view_type
Definition: multi_array.hxx:2405
const difference_type & shape() const
Definition: multi_array.hxx:1602
ActualDimension
Definition: multi_array.hxx:777
MultiArrayView< N, T, StrideTag > view_type
Definition: multi_array.hxx:831
difference_type m_shape
Definition: multi_array.hxx:843
MultiArray(allocator_type const &alloc)
Definition: multi_array.hxx:2504
MultiArray & operator=(value_type const &v)
Definition: multi_array.hxx:2586
A allocator_type
Definition: multi_array.hxx:2401
U product() const
Definition: multi_array.hxx:1787
reference operator[](difference_type_1 d)
Definition: multi_array.hxx:1089
MultiArrayView & operator-=(T const &rhs)
Definition: multi_array.hxx:983
difference_type size_type
Definition: multi_array.hxx:805
MultiArrayView & operator*=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:1039
pointer data() const
Definition: multi_array.hxx:1829
void deallocate(pointer &ptr, difference_type_1 s)
Definition: multi_array.hxx:2991
difference_type_1 elementCount() const
Definition: multi_array.hxx:1584
const_iterator end() const
Definition: multi_array.hxx:2798
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition: fftw3.hxx:1044
MultiArrayView & operator-=(MultiArrayView< N, U, C1 > const &rhs)
iterator begin()
Definition: multi_array.hxx:1852
Main MultiArray class containing the memory management.
Definition: multi_array.hxx:595
vigra::detail::MultiIteratorChooser< UnstridedArrayTag >::template Traverser< N, T, T &, T * >::type traverser
Definition: multi_array.hxx:2447
MultiArrayView & operator/=(T const &rhs)
Definition: multi_array.hxx:999
BasicImageView< T > makeBasicImageView(MultiArrayView< 2, T, UnstridedArrayTag > const &array)
Definition: multi_array.hxx:3315
void reshape(const difference_type &shape)
Definition: multi_array.hxx:2756
reference operator()(difference_type_1 x)
Definition: multi_array.hxx:1129
std::ptrdiff_t MultiArrayIndex
Definition: multi_iterator.hxx:348
Find the sum of the pixel values in an image or ROI.
Definition: inspectimage.hxx:947
MultiArrayView subarray(const difference_type &p, const difference_type &q) const
Definition: multi_array.hxx:1490
const_iterator begin() const
Definition: multi_array.hxx:1860
StridedScanOrderIterator< actual_dimension, T, T &, T * > iterator
Definition: multi_array.hxx:813
vigra::detail::MultiIteratorChooser< StrideTag >::template Traverser< actual_dimension, T, T const &, T const * >::type const_traverser
Definition: multi_array.hxx:827
MultiArrayView & operator/=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:1049
NormTraits< MultiArrayView >::NormType norm(int type=2, bool useSquaredNorm=true) const
Definition: multi_array.hxx:2289
MultiArrayView< N, T, StridedArrayTag > transpose() const
Definition: multi_array.hxx:1528
view_type::difference_type difference_type
Definition: multi_array.hxx:2437
void meanVariance(U *mean, U *variance) const
Definition: multi_array.hxx:1711
MultiArray(multi_math::MultiMathOperand< Expression > const &rhs, allocator_type const &alloc=allocator_type())
Definition: multi_array.hxx:2544
MultiArrayView< N+1, T, StrideTag > insertSingletonDimension(difference_type_1 i) const
Definition: multi_array.hxx:2271
MultiArrayView< N-M, T, StridedArrayTag > bindInner(const TinyVector< Index, M > &d) const
Definition: multi_array.hxx:2124
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition: fftw3.hxx:1037
vigra::detail::MultiIteratorChooser< StrideTag >::template Traverser< actual_dimension, T, T &, T * >::type traverser
Definition: multi_array.hxx:822
MultiArrayView & operator=(MultiArrayView const &rhs)
Definition: multi_array.hxx:1929
difference_type_1 size() const
Definition: multi_array.hxx:1595
void swapData(MultiArrayView< N, T2, C2 > rhs)
Definition: multi_array.hxx:1254
NormTraits< MultiArrayView >::SquaredNormType squaredNorm() const
Definition: multi_array.hxx:1800
Definition: multi_iterator.hxx:354
bool operator==(MultiArrayView< N, U, C1 > const &rhs) const
Definition: multi_array.hxx:1639
view_type::reference reference
Definition: multi_array.hxx:2425
MultiArrayIndex difference_type_1
Definition: multi_array.hxx:809
const difference_type & stride() const
Definition: multi_array.hxx:1624
bool any() const
Definition: multi_array.hxx:1681
T * iterator
Definition: multi_array.hxx:2457
bool operator!=(MultiArrayView< N, U, C1 > const &rhs) const
Definition: multi_array.hxx:1650
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:1683
MultiArray & operator*=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2719
value_type & reference
Definition: multi_array.hxx:785
MultiArrayView & operator-=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:1029
const_reference operator[](difference_type_1 d) const
Definition: multi_array.hxx:1105
difference_type_1 stride(int n) const
Definition: multi_array.hxx:1631
T * const_iterator
Definition: multi_array.hxx:2461
bool isInside(difference_type const &p) const
Definition: multi_array.hxx:1657
difference_type_1 coordinateToScanOrderIndex(const difference_type &d) const
Definition: multi_array.hxx:1122
const_iterator end() const
Definition: multi_array.hxx:1876
MultiArray & init(const U &init)
Definition: multi_array.hxx:2746
MultiArrayView< 1, T, StridedArrayTag > diagonal() const
Definition: multi_array.hxx:1471
MultiArrayView< N-1, T, StridedArrayTag > bindAt(difference_type_1 m, difference_type_1 d) const
Definition: multi_array.hxx:2213
allocator_type m_alloc
Definition: multi_array.hxx:2469
void minmax(T *minimum, T *maximum) const
Definition: multi_array.hxx:1695
void copy(const MultiArrayView< N, U, CN > &rhs)
Definition: multi_array.hxx:1234
BasicImage using foreign memory.
Definition: basicimageview.hxx:75
MultiArrayView< N, T, StridedArrayTag > permuteStridesDescending() const
Definition: multi_array.hxx:2090
void copy(const MultiArrayView &rhs)
Definition: multi_array.hxx:1224
difference_type scanOrderIndexToCoordinate(difference_type_1 d) const
Definition: multi_array.hxx:1113
Definition: metaprogramming.hxx:102
allocator_type const & allocator() const
Definition: multi_array.hxx:2805
const_iterator begin() const
Definition: multi_array.hxx:2791
MultiArrayView< N, typename ExpandElementResult< T >::type, StridedArrayTag > bindElementChannel(difference_type_1 i) const
Definition: multi_array.hxx:1395
view_type::size_type size_type
Definition: multi_array.hxx:2433
MultiArrayView & operator/=(MultiArrayView< N, U, C1 > const &rhs)
difference_type_1 size(difference_type_1 n) const
Definition: multi_array.hxx:1609
view_type::const_pointer const_pointer
Definition: multi_array.hxx:2421
view_type::value_type value_type
Definition: multi_array.hxx:2413
Definition: metaprogramming.hxx:117
const_traverser traverser_begin() const
Definition: multi_array.hxx:1893
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:939
T value_type
Definition: multi_array.hxx:781
MultiArrayView< N, T, StridedArrayTag > permuteDimensions(const difference_type &s) const
Definition: multi_array.hxx:2037
bool hasData() const
Definition: multi_array.hxx:1844
pointer m_ptr
Definition: multi_array.hxx:852
~MultiArray()
Definition: multi_array.hxx:2737
view_type::difference_type_1 difference_type_1
Definition: multi_array.hxx:2441
MultiArrayView & operator+=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:1019
MultiArrayShape< 1 >::type Shape1
shape type for MultiArray<1, T>
Definition: multi_iterator.hxx:363
MultiArrayView & operator=(MultiArrayView< N, U, C1 > const &rhs)
Definition: multi_array.hxx:934
MultiArray(const MultiArray &rhs)
Definition: multi_array.hxx:2534
Encapsulate read access to the values an iterator points to.
Definition: accessor.hxx:268
bool isUnstrided(unsigned int dimension=N-1) const
Definition: multi_array.hxx:1265
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:593
iterator end()
Definition: multi_array.hxx:2784
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
MultiArrayView & init(const U &init)
Definition: multi_array.hxx:1214
MultiArray & operator-=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2709
iterator begin()
Definition: multi_array.hxx:2777
MultiArrayView(const difference_type &shape, const difference_type &stride, pointer ptr)
Definition: multi_array.hxx:901
void swapData(MultiArrayView rhs)
Definition: multi_array.hxx:1243
value_type * pointer
Definition: multi_array.hxx:793
MultiArrayView(const difference_type &shape, pointer ptr)
Definition: multi_array.hxx:890
traverser traverser_end()
Definition: multi_array.hxx:1903
Class for a single RGB value.
Definition: accessor.hxx:937
bool all() const
Definition: multi_array.hxx:1668
MultiArrayView< N-1, T, typename vigra::detail::MaybeStrided< StrideTag, M >::type > bind(difference_type_1 d) const
StridedScanOrderIterator< actual_dimension, T, T const &, T const * > const_iterator
Definition: multi_array.hxx:817
reference operator[](const difference_type &d)
Definition: multi_array.hxx:1057
MultiArrayView< N+1, typename ExpandElementResult< T >::type, StridedArrayTag > expandElements(difference_type_1 d) const
Definition: multi_array.hxx:2242
MultiArrayView & operator*=(T const &rhs)
Definition: multi_array.hxx:991
MultiArrayView< N, T, StridedArrayTag > permuteStridesAscending() const
Definition: multi_array.hxx:2080
difference_type m_stride
Definition: multi_array.hxx:848
void init(Iterator i, Iterator end)
Definition: tinyvector.hxx:611
U sum() const
Definition: multi_array.hxx:1734
const value_type * const_pointer
Definition: multi_array.hxx:797
difference_type_1 shape(difference_type_1 n) const
Definition: multi_array.hxx:1617
traverser traverser_begin()
Definition: multi_array.hxx:1884
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
MultiArrayView< N, T, StridedArrayTag > stridearray(const difference_type &s) const
Definition: multi_array.hxx:1504
MultiArrayView()
Definition: multi_array.hxx:884
MultiArrayView< N-M, T, StrideTag > bindOuter(const TinyVector< Index, M > &d) const
Definition: multi_array.hxx:2101
V const & min(TinyVectorBase< V, SIZE, D1, D2 > const &l)
minimum element
Definition: tinyvector.hxx:1771
view_type::const_reference const_reference
Definition: multi_array.hxx:2429
void allocate(pointer &ptr, difference_type_1 s, const_reference init)
Definition: multi_array.hxx:2935
MultiArrayView & operator+=(MultiArrayView< N, U, C1 > const &rhs)
const_traverser traverser_end() const
Definition: multi_array.hxx:1914
difference_type strideOrdering() const
Definition: multi_array.hxx:1571

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Sun Aug 10 2014)