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

multi_array.hxx VIGRA

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

© 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.11.0 (Thu Mar 17 2016)