[ 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 whether the array's inner dimension is strided
641  or not. An array is unstrided if the array elements occupy consecutive
642  memory location, strided if there is an offset in between (e.g.
643  when a view is created that skips every other array element).
644  The compiler can generate faster code for unstrided arrays.
645  Possible values: StridedArrayTag (default), UnstridedArrayTag
646 \endcode
647 
648 <b>\#include</b> <vigra/multi_array.hxx> <br/>
649 Namespace: vigra
650 */
651 template <unsigned int N, class T, class StrideTag>
653 {
654 public:
655 
656  /** the array's actual dimensionality.
657  This ensures that MultiArrayView can also be used for
658  scalars (that is, when <tt>N == 0</tt>). Calculated as:<br>
659  \code
660  actual_dimension = (N==0) ? 1 : N
661  \endcode
662  */
663  enum ActualDimension { actual_dimension = (N==0) ? 1 : N };
664 
665  /** the array's value type
666  */
667  typedef T value_type;
668 
669  /** reference type (result of operator[])
670  */
671  typedef value_type &reference;
672 
673  /** const reference type (result of operator[] const)
674  */
675  typedef const value_type &const_reference;
676 
677  /** pointer type
678  */
679  typedef value_type *pointer;
680 
681  /** const pointer type
682  */
683  typedef const value_type *const_pointer;
684 
685  /** difference type (used for multi-dimensional offsets and indices)
686  */
688 
689  /** key type (argument of index operator array[i] -- same as difference_type)
690  */
691  typedef difference_type key_type;
692 
693  /** size type
694  */
695  typedef difference_type size_type;
696 
697  /** difference and index type for a single dimension
698  */
700 
701  /** scan-order iterator (StridedScanOrderIterator) type
702  */
704 
705  /** const scan-order iterator (StridedScanOrderIterator) type
706  */
708 
709  /** traverser (MultiIterator) type
710  */
711  typedef typename vigra::detail::MultiIteratorChooser <
712  StrideTag>::template Traverser <actual_dimension, T, T &, T *>::type traverser;
713 
714  /** const traverser (MultiIterator) type
715  */
716  typedef typename vigra::detail::MultiIteratorChooser <
717  StrideTag>::template Traverser <actual_dimension, T, T const &, T const *>::type const_traverser;
718 
719  /** the view type associated with this array.
720  */
722 
723  /** the matrix type associated with this array.
724  */
726 
727  bool checkInnerStride(UnstridedArrayTag) const
728  {
729  return m_stride[0] <= 1;
730  }
731 
732  bool checkInnerStride(StridedArrayTag) const
733  {
734  return true;
735  }
736 
737  protected:
738 
739  typedef typename difference_type::value_type diff_zero_t;
740 
741  /** the shape of the image pointed to is stored here.
742  */
743  difference_type m_shape;
744 
745  /** the strides (offset of a sample to the next) for every dimension
746  are stored here.
747  */
748  difference_type m_stride;
749 
750  /** pointer to the image.
751  */
752  pointer m_ptr;
753 
754  template <class CN>
755  void assignImpl(const MultiArrayView <N, T, CN>& rhs);
756 
757  template <class U, class CN>
758  void copyImpl(const MultiArrayView <N, U, CN>& rhs);
759 
760  template <class U, class CN>
761  void swapDataImpl(MultiArrayView <N, U, CN> rhs);
762 
763  template <class CN>
764  bool arraysOverlap(const MultiArrayView <N, T, CN>& rhs) const;
765 
766  template <class U, class CN>
767  bool arraysOverlap(const MultiArrayView <N, U, CN>&) const
768  {
769  return false;
770  }
771 
772 public:
773 
774  /** default constructor: create an invalid view,
775  * i.e. hasData() returns false and size() is zero.
776  */
778  : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0)
779  {}
780 
781  /** construct from another array view.
782  Throws a precondition error if this array has UnstridedArrayTag, but the
783  innermost dimension of \a other is strided.
784  */
785  template <class Stride>
787  : m_shape (other.shape()),
788  m_stride (other.stride()),
789  m_ptr (other.data())
790  {
791  vigra_precondition(other.checkInnerStride(StrideTag()),
792  "MultiArrayView<..., UnstridedArrayTag>(MultiArrayView const &): cannot create unstrided view from strided array.");
793  }
794 
795  /** construct from shape and pointer
796  */
797  MultiArrayView (const difference_type &shape, const_pointer ptr)
798  : m_shape (shape),
799  m_stride (detail::defaultStride<actual_dimension>(shape)),
800  m_ptr (const_cast<pointer>(ptr))
801  {}
802 
803  /** Construct from shape, strides (offset of a sample to the
804  next) for every dimension, and pointer. (Note that
805  strides are not given in bytes, but in offset steps of the
806  respective pointer type.)
807  */
808  MultiArrayView (const difference_type &shape,
809  const difference_type &stride,
810  const_pointer ptr)
811  : m_shape (shape),
812  m_stride (stride),
813  m_ptr (const_cast<pointer>(ptr))
814  {
815  vigra_precondition(checkInnerStride(StrideTag()),
816  "MultiArrayView<..., UnstridedArrayTag>::MultiArrayView(): First dimension of given array is not unstrided.");
817  }
818 
819  /** Construct from an old-style BasicImage.
820  */
821  template <class ALLOC>
823  : m_shape (Shape2(image.width(), image.height())),
824  m_stride (detail::defaultStride<actual_dimension>(m_shape)),
825  m_ptr (const_cast<pointer>(image.data()))
826  {}
827 
828  /** Conversion to a strided view.
829  */
831  {
832  return MultiArrayView<N, T, StridedArrayTag>(m_shape, m_stride, m_ptr);
833  }
834 
835  /** Reset this <tt>MultiArrayView</tt> to an invalid state (as after default construction).
836  Can e.g. be used prior to assignment to make a view object point to new data.
837  */
838  void reset() {
839  m_shape = diff_zero_t(0);
840  m_stride = diff_zero_t(0);
841  m_ptr = 0;
842  }
843 
844 
845  /** Assignment. There are 3 cases:
846 
847  <ul>
848  <li> When this <tt>MultiArrayView</tt> does not point to valid data
849  (e.g. after default construction), it becomes a new view of \a rhs.
850  <li> Otherwise, when the shapes of the two arrays match, the contents
851  (i.e. the elements) of \a rhs are copied.
852  <li> Otherwise, a <tt>PreconditionViolation</tt> exception is thrown.
853  </ul>
854  */
856  {
857  if(this != &rhs)
858  assignImpl(rhs);
859  return *this;
860  }
861 
862  template<class Stride2>
863  MultiArrayView & operator=(MultiArrayView<N, T, Stride2> const & rhs)
864  {
865  assignImpl(rhs);
866  return *this;
867  }
868 
869  /** Assignment of a differently typed MultiArrayView. It copies the elements
870  of\a rhs or fails with <tt>PreconditionViolation</tt> exception when
871  the shapes do not match.
872  */
873  template<class U, class C1>
875  {
876  vigra_precondition(this->shape() == rhs.shape(),
877  "MultiArrayView::operator=(): shape mismatch.");
878  this->copyImpl(rhs);
879  return *this;
880  }
881 
882  /** Assignment of a scalar. Equivalent to MultiArrayView::init(v).
883  */
884  MultiArrayView & operator=(value_type const & v)
885  {
886  return init(v);
887  }
888 
889  /** Add-assignment of a compatible MultiArrayView. Fails with
890  <tt>PreconditionViolation</tt> exception when the shapes do not match.
891  */
892  template<class U, class C1>
894 
895  /** Subtract-assignment of a compatible MultiArrayView. Fails with
896  <tt>PreconditionViolation</tt> exception when the shapes do not match.
897  */
898  template<class U, class C1>
900 
901  /** Multiply-assignment of a compatible MultiArrayView. Fails with
902  <tt>PreconditionViolation</tt> exception when the shapes do not match.
903  */
904  template<class U, class C1>
906 
907  /** Divide-assignment of a compatible MultiArrayView. Fails with
908  <tt>PreconditionViolation</tt> exception when the shapes do not match.
909  */
910  template<class U, class C1>
912 
913  /** Add-assignment of a scalar.
914  */
915  MultiArrayView & operator+=(T const & rhs)
916  {
917  detail::copyAddScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
918  return *this;
919  }
920 
921  /** Subtract-assignment of a scalar.
922  */
923  MultiArrayView & operator-=(T const & rhs)
924  {
925  detail::copySubScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
926  return *this;
927  }
928 
929  /** Multiply-assignment of a scalar.
930  */
931  MultiArrayView & operator*=(T const & rhs)
932  {
933  detail::copyMulScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
934  return *this;
935  }
936 
937  /** Divide-assignment of a scalar.
938  */
939  MultiArrayView & operator/=(T const & rhs)
940  {
941  detail::copyDivScalarMultiArrayData(traverser_begin(), shape(), rhs, MetaInt<actual_dimension-1>());
942  return *this;
943  }
944 
945  /** Assignment of an array expression. Fails with
946  <tt>PreconditionViolation</tt> exception when the shapes do not match.
947  */
948  template<class Expression>
949  MultiArrayView & operator=(multi_math::MultiMathOperand<Expression> const & rhs)
950  {
951  multi_math::math_detail::assign(*this, rhs);
952  return *this;
953  }
954 
955  /** Add-assignment of an array expression. Fails with
956  <tt>PreconditionViolation</tt> exception when the shapes do not match.
957  */
958  template<class Expression>
959  MultiArrayView & operator+=(multi_math::MultiMathOperand<Expression> const & rhs)
960  {
961  multi_math::math_detail::plusAssign(*this, rhs);
962  return *this;
963  }
964 
965  /** Subtract-assignment of an array expression. Fails with
966  <tt>PreconditionViolation</tt> exception when the shapes do not match.
967  */
968  template<class Expression>
969  MultiArrayView & operator-=(multi_math::MultiMathOperand<Expression> const & rhs)
970  {
971  multi_math::math_detail::minusAssign(*this, rhs);
972  return *this;
973  }
974 
975  /** Multiply-assignment of an array expression. Fails with
976  <tt>PreconditionViolation</tt> exception when the shapes do not match.
977  */
978  template<class Expression>
979  MultiArrayView & operator*=(multi_math::MultiMathOperand<Expression> const & rhs)
980  {
981  multi_math::math_detail::multiplyAssign(*this, rhs);
982  return *this;
983  }
984 
985  /** Divide-assignment of an array expression. Fails with
986  <tt>PreconditionViolation</tt> exception when the shapes do not match.
987  */
988  template<class Expression>
989  MultiArrayView & operator/=(multi_math::MultiMathOperand<Expression> const & rhs)
990  {
991  multi_math::math_detail::divideAssign(*this, rhs);
992  return *this;
993  }
994 
995  /** array access.
996  */
997  reference operator[] (const difference_type &d)
998  {
999  VIGRA_ASSERT_INSIDE(d);
1000  return m_ptr [dot (d, m_stride)];
1001  }
1002 
1003  /** array access.
1004  */
1005  const_reference operator[] (const difference_type &d) const
1006  {
1007  VIGRA_ASSERT_INSIDE(d);
1008  return m_ptr [dot (d, m_stride)];
1009  }
1010 
1011  /** equivalent to bindInner(), when M < N.
1012  */
1013  template <int M>
1014  MultiArrayView <N-M, T, StridedArrayTag> operator[] (const TinyVector<MultiArrayIndex, M> &d) const
1015  {
1016  return bindInner(d);
1017  }
1018 
1019  /** Array access in scan-order sense.
1020  Mostly useful to support standard indexing for 1-dimensional multi-arrays,
1021  but works for any N. Use scanOrderIndexToCoordinate() and
1022  coordinateToScanOrderIndex() for conversion between indices and coordinates.
1023 
1024  <b>Note:</b> This function should not be used in the inner loop, because the
1025  conversion of the scan order index into a memory address is expensive
1026  (it must take into account that memory may not be consecutive for subarrays
1027  and/or strided arrays). Always prefer operator() if possible.
1028  */
1029  reference operator[](difference_type_1 d)
1030  {
1031  VIGRA_ASSERT_INSIDE(scanOrderIndexToCoordinate(d));
1032  return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
1033  }
1034 
1035  /** Array access in scan-order sense.
1036  Mostly useful to support standard indexing for 1-dimensional multi-arrays,
1037  but works for any N. Use scanOrderIndexToCoordinate() and
1038  coordinateToScanOrderIndex() for conversion between indices and coordinates.
1039 
1040  <b>Note:</b> This function should not be used in the inner loop, because the
1041  conversion of the scan order index into a memory address is expensive
1042  (it must take into account that memory may not be consecutive for subarrays
1043  and/or strided arrays). Always prefer operator() if possible.
1044  */
1045  const_reference operator[](difference_type_1 d) const
1046  {
1047  VIGRA_ASSERT_INSIDE(scanOrderIndexToCoordinate(d));
1048  return m_ptr [detail::ScanOrderToOffset<actual_dimension>::exec(d, m_shape, m_stride)];
1049  }
1050 
1051  /** convert scan-order index to coordinate.
1052  */
1053  difference_type scanOrderIndexToCoordinate(difference_type_1 d) const
1054  {
1055  difference_type result;
1056  detail::ScanOrderToCoordinate<actual_dimension>::exec(d, m_shape, result);
1057  return result;
1058  }
1059 
1060  /** convert coordinate to scan-order index.
1061  */
1062  difference_type_1 coordinateToScanOrderIndex(const difference_type &d) const
1063  {
1064  return detail::CoordinateToScanOrder<actual_dimension>::exec(m_shape, d);
1065  }
1066 
1067  /** 1D array access. Use only if N == 1.
1068  */
1069  reference operator() (difference_type_1 x)
1070  {
1071  VIGRA_ASSERT_INSIDE(difference_type(x));
1072  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x)];
1073  }
1074 
1075  /** 2D array access. Use only if N == 2.
1076  */
1077  reference operator() (difference_type_1 x, difference_type_1 y)
1078  {
1079  VIGRA_ASSERT_INSIDE(difference_type(x, y));
1080  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x, y)];
1081  }
1082 
1083  /** 3D array access. Use only if N == 3.
1084  */
1085  reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z)
1086  {
1087  VIGRA_ASSERT_INSIDE(difference_type(x, y, z));
1088  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
1089  }
1090 
1091  /** 4D array access. Use only if N == 4.
1092  */
1093  reference operator() (difference_type_1 x, difference_type_1 y,
1094  difference_type_1 z, difference_type_1 u)
1095  {
1096  VIGRA_ASSERT_INSIDE(difference_type(x, y, z, u));
1097  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
1098  }
1099 
1100  /** 5D array access. Use only if N == 5.
1101  */
1102  reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z,
1103  difference_type_1 u, difference_type_1 v)
1104  {
1105  VIGRA_ASSERT_INSIDE(difference_type(x, y,z, u,v));
1106  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
1107  }
1108 
1109  /** 1D const array access. Use only if N == 1.
1110  */
1111  const_reference operator() (difference_type_1 x) const
1112  {
1113  VIGRA_ASSERT_INSIDE(difference_type(x));
1114  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x)];
1115  }
1116 
1117  /** 2D const array access. Use only if N == 2.
1118  */
1119  const_reference operator() (difference_type_1 x, difference_type_1 y) const
1120  {
1121  VIGRA_ASSERT_INSIDE(difference_type(x, y));
1122  return m_ptr [detail::CoordinatesToOffest<StrideTag>::exec(m_stride, x, y)];
1123  }
1124 
1125  /** 3D const array access. Use only if N == 3.
1126  */
1127  const_reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z) const
1128  {
1129  VIGRA_ASSERT_INSIDE(difference_type(x,y,z));
1130  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z];
1131  }
1132 
1133  /** 4D const array access. Use only if N == 4.
1134  */
1135  const_reference operator() (difference_type_1 x, difference_type_1 y,
1136  difference_type_1 z, difference_type_1 u) const
1137  {
1138  VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u));
1139  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u];
1140  }
1141 
1142  /** 5D const array access. Use only if N == 5.
1143  */
1144  const_reference operator() (difference_type_1 x, difference_type_1 y, difference_type_1 z,
1145  difference_type_1 u, difference_type_1 v) const
1146  {
1147  VIGRA_ASSERT_INSIDE(difference_type(x,y,z,u,v));
1148  return m_ptr [m_stride[0]*x + m_stride[1]*y + m_stride[2]*z + m_stride[3]*u + m_stride[4]*v];
1149  }
1150 
1151  /** Init with a constant.
1152  */
1153  template <class U>
1154  MultiArrayView & init(const U & init)
1155  {
1156  if(hasData())
1157  detail::copyScalarMultiArrayData(traverser_begin(), shape(), init, MetaInt<actual_dimension-1>());
1158  return *this;
1159  }
1160 
1161 
1162  /** Copy the data of the right-hand array (array shapes must match).
1163  */
1164  void copy(const MultiArrayView & rhs)
1165  {
1166  if(this == &rhs)
1167  return;
1168  this->copyImpl(rhs);
1169  }
1170 
1171  /** Copy the data of the right-hand array (array shapes must match).
1172  */
1173  template <class U, class CN>
1175  {
1176  this->copyImpl(rhs);
1177  }
1178 
1179  /** Swap the pointers, shaes and strides between two array views.
1180 
1181  This function must be used with care. Never swap a MultiArray
1182  (which owns data) with a MultiArrayView:
1183  \code
1184  MultiArray<2, int> a(3,2), b(3,2);
1185  MultiArrayView<2, int> va(a);
1186 
1187  va.swap(b); // danger!
1188  \endcode
1189  Now, <tt>a</tt> and <tt>b</tt> refer to the same memory. This may lead
1190  to a crash in their destructor, and in any case leaks <tt>b</tt>'s original
1191  memory. Only use swap() on copied MultiArrayViews:
1192  \code
1193  MultiArray<2, int> a(3,2), b(3,2);
1194  MultiArrayView<2, int> va(a), vb(b);
1195 
1196  va.swap(vb); // OK
1197  \endcode
1198  */
1199  void swap(MultiArrayView & other)
1200  {
1201  if (this == &other)
1202  return;
1203  std::swap(this->m_shape, other.m_shape);
1204  std::swap(this->m_stride, other.m_stride);
1205  std::swap(this->m_ptr, other.m_ptr);
1206  }
1207 
1208  /** swap the data between two MultiArrayView objects.
1209 
1210  The shapes of the two array must match.
1211  */
1213  {
1214  if(this != &rhs)
1215  swapDataImpl(rhs);
1216  }
1217 
1218  /** swap the data between two MultiArrayView objects.
1219 
1220  The shapes of the two array must match.
1221  */
1222  template <class T2, class C2>
1224  {
1225  swapDataImpl(rhs);
1226  }
1227 
1228  /** check whether the array is unstrided (i.e. has consecutive memory) up
1229  to the given dimension.
1230 
1231  \a dimension can range from 0 ... N-1. If a certain dimension is unstrided,
1232  all lower dimensions are also unstrided.
1233  */
1234  bool isUnstrided(unsigned int dimension = N-1) const
1235  {
1236  difference_type s = vigra::detail::defaultStride<actual_dimension>(shape());
1237  for(unsigned int k = 0; k <= dimension; ++k)
1238  if(stride(k) != s[k])
1239  return false;
1240  return true;
1241  }
1242 
1243  /** bind the M outmost dimensions to certain indices.
1244  this reduces the dimensionality of the image to
1245  max { 1, N-M }.
1246 
1247  <b>Usage:</b>
1248  \code
1249  // create a 3D array of size 40x30x20
1250  typedef MultiArray<3, double>::difference_type Shape;
1251  MultiArray<3, double> array3(Shape(40, 30, 20));
1252 
1253  // get a 1D array by fixing index 1 to 12, and index 2 to 10
1254  MultiArrayView <1, double> array1 = array3.bindOuter(TinyVector<MultiArrayIndex, 2>(12, 10));
1255  \endcode
1256  */
1257  template <int M, class Index>
1258  MultiArrayView <N-M, T, StrideTag> bindOuter(const TinyVector <Index, M> &d) const;
1259 
1260  /** bind the M innermost dimensions to certain indices.
1261  this reduces the dimensionality of the image to
1262  max { 1, N-M }.
1263 
1264  <b>Usage:</b>
1265  \code
1266  // create a 3D array of size 40x30x20
1267  typedef MultiArray<3, double>::difference_type Shape;
1268  MultiArray<3, double> array3(Shape(40, 30, 20));
1269 
1270  // get a 1D array by fixing index 0 to 12, and index 1 to 10
1271  MultiArrayView <1, double, StridedArrayTag> array1 = array3.bindInner(TinyVector<MultiArrayIndex, 2>(12, 10));
1272  \endcode
1273  */
1274  template <int M, class Index>
1275  MultiArrayView <N-M, T, StridedArrayTag> bindInner(const TinyVector <Index, M> &d) const;
1276 
1277  /** bind dimension M to index d.
1278  this reduces the dimensionality of the image to
1279  max { 1, N-1 }.
1280 
1281  <b>Usage:</b>
1282  \code
1283  // create a 3D array of size 40x30x20
1284  typedef MultiArray<3, double>::difference_type Shape;
1285  MultiArray<3, double> array3(Shape(40, 30, 20));
1286 
1287  // get a 2D array by fixing index 1 to 12
1288  MultiArrayView <2, double> array2 = array3.bind<1>(12);
1289 
1290  // get a 2D array by fixing index 0 to 23
1291  MultiArrayView <2, double, StridedArrayTag> array2a = array3.bind<0>(23);
1292  \endcode
1293  */
1294  template <unsigned int M>
1295  MultiArrayView <N-1, T, typename vigra::detail::MaybeStrided<StrideTag, M>::type >
1296  bind (difference_type_1 d) const;
1297 
1298  /** bind the outmost dimension to a certain index.
1299  this reduces the dimensionality of the image to
1300  max { 1, N-1 }.
1301 
1302  <b>Usage:</b>
1303  \code
1304  // create a 3D array of size 40x30x20
1305  typedef MultiArray<3, double>::difference_type Shape;
1306  MultiArray<3, double> array3(Shape(40, 30, 20));
1307 
1308  // get a 2D array by fixing the outermost index (i.e. index 2) to 12
1309  MultiArrayView <2, double> array2 = array3.bindOuter(12);
1310  \endcode
1311  */
1312  MultiArrayView <N-1, T, StrideTag> bindOuter (difference_type_1 d) const;
1313 
1314  /** bind the innermost dimension to a certain index.
1315  this reduces the dimensionality of the image to
1316  max { 1, N-1 }.
1317 
1318  <b>Usage:</b>
1319  \code
1320  // create a 3D array of size 40x30x20
1321  typedef MultiArray<3, double>::difference_type Shape;
1322  MultiArray<3, double> array3(Shape(40, 30, 20));
1323 
1324  // get a 2D array by fixing the innermost index (i.e. index 0) to 23
1325  MultiArrayView <2, double, StridedArrayTag> array2 = array3.bindInner(23);
1326  \endcode
1327  */
1328  MultiArrayView <N-1, T, StridedArrayTag> bindInner (difference_type_1 d) const;
1329 
1330  /** bind dimension m to index d.
1331  this reduces the dimensionality of the image to
1332  max { 1, N-1 }.
1333 
1334  <b>Usage:</b>
1335  \code
1336  // create a 3D array of size 40x30x20
1337  typedef MultiArray<3, double>::difference_type Shape;
1338  MultiArray<3, double> array3(Shape(40, 30, 20));
1339 
1340  // get a 2D array by fixing index 2 to 15
1341  MultiArrayView <2, double, StridedArrayTag> array2 = array3.bindAt(2, 15);
1342  \endcode
1343  */
1345  bindAt (difference_type_1 m, difference_type_1 d) const;
1346 
1347  /** Create a view to channel 'i' of a vector-like value type. Possible value types
1348  (of the original array) are: \ref TinyVector, \ref RGBValue, \ref FFTWComplex,
1349  and <tt>std::complex</tt>. The list can be extended to any type whose memory
1350  layout is equivalent to a fixed-size C array, by specializing
1351  <tt>ExpandElementResult</tt>.
1352 
1353  <b>Usage:</b>
1354  \code
1355  MultiArray<2, RGBValue<float> > rgb_image(Shape2(w, h));
1356 
1357  MultiArrayView<2, float, StridedArrayTag> red = rgb_image.bindElementChannel(0);
1358  MultiArrayView<2, float, StridedArrayTag> green = rgb_image.bindElementChannel(1);
1359  MultiArrayView<2, float, StridedArrayTag> blue = rgb_image.bindElementChannel(2);
1360  \endcode
1361  */
1363  bindElementChannel(difference_type_1 i) const
1364  {
1365  vigra_precondition(0 <= i && i < ExpandElementResult<T>::size,
1366  "MultiArrayView::bindElementChannel(i): 'i' out of range.");
1367  return expandElements(0).bindInner(i);
1368  }
1369 
1370  /** Create a view where a vector-like element type is expanded into a new
1371  array dimension. The new dimension is inserted at index position 'd',
1372  which must be between 0 and N inclusive.
1373 
1374  Possible value types of the original array are: \ref TinyVector, \ref RGBValue,
1375  \ref FFTWComplex, <tt>std::complex</tt>, and the built-in number types (in this
1376  case, <tt>expandElements</tt> is equivalent to <tt>insertSingletonDimension</tt>).
1377  The list of supported types can be extended to any type whose memory
1378  layout is equivalent to a fixed-size C array, by specializing
1379  <tt>ExpandElementResult</tt>.
1380 
1381  <b>Usage:</b>
1382  \code
1383  MultiArray<2, RGBValue<float> > rgb_image(Shape2(w, h));
1384 
1385  MultiArrayView<3, float, StridedArrayTag> multiband_image = rgb_image.expandElements(2);
1386  \endcode
1387  */
1389  expandElements(difference_type_1 d) const;
1390 
1391  /** Add a singleton dimension (dimension of length 1).
1392 
1393  Singleton dimensions don't change the size of the data, but introduce
1394  a new index that can only take the value 0. This is mainly useful for
1395  the 'reduce mode' of transformMultiArray() and combineTwoMultiArrays(),
1396  because these functions require the source and destination arrays to
1397  have the same number of dimensions.
1398 
1399  The range of \a i must be <tt>0 <= i <= N</tt>. The new dimension will become
1400  the i'th index, and the old indices from i upwards will shift one
1401  place to the right.
1402 
1403  <b>Usage:</b>
1404 
1405  Suppose we want have a 2D array and want to create a 1D array that contains
1406  the row average of the first array.
1407  \code
1408  typedef MultiArrayShape<2>::type Shape2;
1409  MultiArray<2, double> original(Shape2(40, 30));
1410 
1411  typedef MultiArrayShape<1>::type Shape1;
1412  MultiArray<1, double> rowAverages(Shape1(30));
1413 
1414  // temporarily add a singleton dimension to the destination array
1415  transformMultiArray(srcMultiArrayRange(original),
1416  destMultiArrayRange(rowAverages.insertSingletonDimension(0)),
1417  FindAverage<double>());
1418  \endcode
1419  */
1421  insertSingletonDimension (difference_type_1 i) const;
1422 
1423  /** create a multiband view for this array.
1424 
1425  The type <tt>MultiArrayView<N, Multiband<T> ></tt> tells VIGRA
1426  algorithms which recognize the <tt>Multiband</tt> modifier to
1427  interpret the outermost (last) dimension as a channel dimension.
1428  In effect, these algorithms will treat the data as a set of
1429  (N-1)-dimensional arrays instead of a single N-dimensional array.
1430  */
1432  {
1433  return MultiArrayView<N, Multiband<value_type>, StrideTag>(*this);
1434  }
1435 
1436  /** Create a view to the diagonal elements of the array.
1437 
1438  This produces a 1D array view whose size equals the size
1439  of the shortest dimension of the original array.
1440 
1441  <b>Usage:</b>
1442  \code
1443  // create a 3D array of size 40x30x20
1444  typedef MultiArray<3, double>::difference_type Shape;
1445  MultiArray<3, double> array3(Shape(40, 30, 20));
1446 
1447  // get a view to the diagonal elements
1448  MultiArrayView <1, double, StridedArrayTag> diagonal = array3.diagonal();
1449  assert(diagonal.shape(0) == 20);
1450  \endcode
1451  */
1453  {
1455  Shape1(vigra::sum(m_stride)), m_ptr);
1456  }
1457 
1458  /** create a rectangular subarray that spans between the
1459  points p and q, where p is in the subarray, q not.
1460  If an element of p or q is negative, it is subtracted
1461  from the correspongng shape.
1462 
1463  <b>Usage:</b>
1464  \code
1465  // create a 3D array of size 40x30x20
1466  typedef MultiArray<3, double>::difference_type Shape;
1467  MultiArray<3, double> array3(Shape(40, 30, 20));
1468 
1469  // get a subarray set is smaller by one element at all sides
1470  MultiArrayView <3, double> subarray = array3.subarray(Shape(1,1,1), Shape(39, 29, 19));
1471 
1472  // specifying the end point with a vector of '-1' is equivalent
1473  MultiArrayView <3, double> subarray2 = array3.subarray(Shape(1,1,1), Shape(-1, -1, -1));
1474  \endcode
1475  */
1476  MultiArrayView subarray (difference_type p, difference_type q) const
1477  {
1478  detail::RelativeToAbsoluteCoordinate<actual_dimension-1>::exec(shape(), p);
1479  detail::RelativeToAbsoluteCoordinate<actual_dimension-1>::exec(shape(), q);
1480  const difference_type_1 offset = dot (m_stride, p);
1481  return MultiArrayView (q - p, m_stride, m_ptr + offset);
1482  }
1483 
1484  /** apply an additional striding to the image, thereby reducing
1485  the shape of the array.
1486  for example, multiplying the stride of dimension one by three
1487  turns an appropriately laid out (interleaved) rgb image into
1488  a single band image.
1489  */
1491  stridearray (const difference_type &s) const
1492  {
1493  difference_type shape = m_shape;
1494  for (unsigned int i = 0; i < actual_dimension; ++i)
1495  shape[i] = (shape[i] + s[i] - 1) / s[i];
1496  return MultiArrayView <N, T, StridedArrayTag>(shape, m_stride * s, m_ptr);
1497  }
1498 
1499  /** Transpose an array. If N==2, this implements the usual matrix transposition.
1500  For N > 2, it reverses the order of the indices.
1501 
1502  <b>Usage:</b><br>
1503  \code
1504  typedef MultiArray<2, double>::difference_type Shape;
1505  MultiArray<2, double> array(10, 20);
1506 
1507  MultiArrayView<2, double, StridedArrayTag> transposed = array.transpose();
1508 
1509  for(int i=0; i<array.shape(0), ++i)
1510  for(int j=0; j<array.shape(1); ++j)
1511  assert(array(i, j) == transposed(j, i));
1512  \endcode
1513  */
1515  transpose () const
1516  {
1517  difference_type shape(m_shape.begin(), ReverseCopy),
1518  stride(m_stride.begin(), ReverseCopy);
1519  return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr);
1520  }
1521 
1522  /** Permute the dimensions of the array.
1523  The function exchanges the orer of the array's axes without copying the data.
1524  Argument\a permutation specifies the desired order such that
1525  <tt>permutation[k] = j</tt> means that axis <tt>j</tt> in the original array
1526  becomes axis <tt>k</tt> in the transposed array.
1527 
1528  <b>Usage:</b><br>
1529  \code
1530  typedef MultiArray<2, double>::difference_type Shape;
1531  MultiArray<2, double> array(10, 20);
1532 
1533  MultiArrayView<2, double, StridedArrayTag> transposed = array.transpose(Shape(1,0));
1534 
1535  for(int i=0; i<array.shape(0), ++i)
1536  for(int j=0; j<array.shape(1); ++j)
1537  assert(array(i, j) == transposed(j, i));
1538  \endcode
1539  */
1541  transpose(const difference_type &permutation) const
1542  {
1543  return permuteDimensions(permutation);
1544  }
1545 
1547  permuteDimensions (const difference_type &s) const;
1548 
1549  /** Permute the dimensions of the array so that the strides are in ascending order.
1550  Determines the appropriate permutation and then calls permuteDimensions().
1551  */
1553  permuteStridesAscending() const;
1554 
1555  /** Permute the dimensions of the array so that the strides are in descending order.
1556  Determines the appropriate permutation and then calls permuteDimensions().
1557  */
1559  permuteStridesDescending() const;
1560 
1561  /** Compute the ordering of the strides in this array.
1562  The result is describes the current permutation of the axes relative
1563  to the standard ascending stride order.
1564  */
1565  difference_type strideOrdering() const
1566  {
1567  return strideOrdering(m_stride);
1568  }
1569 
1570  /** Compute the ordering of the given strides.
1571  The result is describes the current permutation of the axes relative
1572  to the standard ascending stride order.
1573  */
1574  static difference_type strideOrdering(difference_type strides);
1575 
1576  /** number of the elements in the array.
1577  */
1578  difference_type_1 elementCount () const
1579  {
1580  difference_type_1 ret = m_shape[0];
1581  for(int i = 1; i < actual_dimension; ++i)
1582  ret *= m_shape[i];
1583  return ret;
1584  }
1585 
1586  /** number of the elements in the array.
1587  Same as <tt>elementCount()</tt>. Mostly useful to support the std::vector interface.
1588  */
1589  difference_type_1 size () const
1590  {
1591  return elementCount();
1592  }
1593 
1594  /** return the array's shape.
1595  */
1596  const difference_type & shape () const
1597  {
1598  return m_shape;
1599  }
1600 
1601  /** return the array's size at a certain dimension.
1602  */
1603  difference_type_1 size (difference_type_1 n) const
1604  {
1605  return m_shape [n];
1606  }
1607 
1608  /** return the array's shape at a certain dimension
1609  (same as <tt>size(n)</tt>).
1610  */
1611  difference_type_1 shape (difference_type_1 n) const
1612  {
1613  return m_shape [n];
1614  }
1615 
1616  /** return the array's width (same as <tt>shape(0)</tt>).
1617  */
1618  difference_type_1 width() const
1619  {
1620  return m_shape [0];
1621  }
1622 
1623  /** return the array's height (same as <tt>shape(1)</tt>).
1624  */
1625  difference_type_1 height() const
1626  {
1627  return m_shape [1];
1628  }
1629 
1630  /** return the array's stride for every dimension.
1631  */
1632  const difference_type & stride () const
1633  {
1634  return m_stride;
1635  }
1636 
1637  /** return the array's stride at a certain dimension.
1638  */
1639  difference_type_1 stride (int n) const
1640  {
1641  return m_stride [n];
1642  }
1643 
1644  /** check whether two arrays are elementwise equal.
1645  */
1646  template <class U, class C1>
1647  bool operator==(MultiArrayView<N, U, C1> const & rhs) const
1648  {
1649  if(this->shape() != rhs.shape())
1650  return false;
1651  return detail::equalityOfMultiArrays(traverser_begin(), shape(), rhs.traverser_begin(), MetaInt<actual_dimension-1>());
1652  }
1653 
1654  /** check whether two arrays are not elementwise equal.
1655  Also true when the two arrays have different shapes.
1656  */
1657  template <class U, class C1>
1658  bool operator!=(MultiArrayView<N, U, C1> const & rhs) const
1659  {
1660  return !operator==(rhs);
1661  }
1662 
1663  /** check whether the given point is in the array range.
1664  */
1665  bool isInside (difference_type const & p) const
1666  {
1667  for(int d=0; d<actual_dimension; ++d)
1668  if(p[d] < 0 || p[d] >= shape(d))
1669  return false;
1670  return true;
1671  }
1672  /** check whether the given point is not in the array range.
1673  */
1674  bool isOutside (difference_type const & p) const
1675  {
1676  for(int d=0; d<actual_dimension; ++d)
1677  if(p[d] < 0 || p[d] >= shape(d))
1678  return true;
1679  return false;
1680  }
1681 
1682  /** Check if the array contains only non-zero elements (or if all elements
1683  are 'true' if the value type is 'bool').
1684  */
1685  bool all() const
1686  {
1687  bool res = true;
1688  detail::reduceOverMultiArray(traverser_begin(), shape(),
1689  res,
1690  detail::AllTrueReduceFunctor(),
1691  MetaInt<actual_dimension-1>());
1692  return res;
1693  }
1694 
1695  /** Check if the array contains a non-zero element (or an element
1696  that is 'true' if the value type is 'bool').
1697  */
1698  bool any() const
1699  {
1700  bool res = false;
1701  detail::reduceOverMultiArray(traverser_begin(), shape(),
1702  res,
1703  detail::AnyTrueReduceFunctor(),
1704  MetaInt<actual_dimension-1>());
1705  return res;
1706  }
1707 
1708  /** Find the minimum and maximum element in this array.
1709  See \ref FeatureAccumulators for a general feature
1710  extraction framework.
1711  */
1712  void minmax(T * minimum, T * maximum) const
1713  {
1714  std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min());
1715  detail::reduceOverMultiArray(traverser_begin(), shape(),
1716  res,
1717  detail::MinmaxReduceFunctor(),
1718  MetaInt<actual_dimension-1>());
1719  *minimum = res.first;
1720  *maximum = res.second;
1721  }
1722 
1723  /** Compute the mean and variance of the values in this array.
1724  See \ref FeatureAccumulators for a general feature
1725  extraction framework.
1726  */
1727  template <class U>
1728  void meanVariance(U * mean, U * variance) const
1729  {
1730  typedef typename NumericTraits<U>::RealPromote R;
1731  R zero = R();
1732  triple<double, R, R> res(0.0, zero, zero);
1733  detail::reduceOverMultiArray(traverser_begin(), shape(),
1734  res,
1735  detail::MeanVarianceReduceFunctor(),
1736  MetaInt<actual_dimension-1>());
1737  *mean = res.second;
1738  *variance = res.third / res.first;
1739  }
1740 
1741  /** Compute the sum of the array elements.
1742 
1743  You must provide the type of the result by an explicit template parameter:
1744  \code
1745  MultiArray<2, UInt8> A(width, height);
1746 
1747  double sum = A.sum<double>();
1748  \endcode
1749  */
1750  template <class U>
1751  U sum() const
1752  {
1753  U res = NumericTraits<U>::zero();
1754  detail::reduceOverMultiArray(traverser_begin(), shape(),
1755  res,
1756  detail::SumReduceFunctor(),
1757  MetaInt<actual_dimension-1>());
1758  return res;
1759  }
1760 
1761  /** Compute the sum of the array elements over selected axes.
1762 
1763  \arg sums must have the same shape as this array, except for the
1764  axes along which the sum is to be accumulated. These axes must be
1765  singletons. Note that you must include <tt>multi_pointoperators.hxx</tt>
1766  for this function to work.
1767 
1768  <b>Usage:</b>
1769  \code
1770  #include <vigra/multi_array.hxx>
1771  #include <vigra/multi_pointoperators.hxx>
1772 
1773  MultiArray<2, double> A(Shape2(rows, cols));
1774  ... // fill A
1775 
1776  // make the first axis a singleton to sum over the first index
1777  MultiArray<2, double> rowSums(Shape2(1, cols));
1778  A.sum(rowSums);
1779 
1780  // this is equivalent to
1781  transformMultiArray(srcMultiArrayRange(A),
1782  destMultiArrayRange(rowSums),
1783  FindSum<double>());
1784  \endcode
1785  */
1786  template <class U, class S>
1787  void sum(MultiArrayView<N, U, S> sums) const
1788  {
1789  transformMultiArray(srcMultiArrayRange(*this),
1790  destMultiArrayRange(sums),
1791  FindSum<U>());
1792  }
1793 
1794  /** Compute the product of the array elements.
1795 
1796  You must provide the type of the result by an explicit template parameter:
1797  \code
1798  MultiArray<2, UInt8> A(width, height);
1799 
1800  double prod = A.product<double>();
1801  \endcode
1802  */
1803  template <class U>
1804  U product() const
1805  {
1806  U res = NumericTraits<U>::one();
1807  detail::reduceOverMultiArray(traverser_begin(), shape(),
1808  res,
1809  detail::ProdReduceFunctor(),
1810  MetaInt<actual_dimension-1>());
1811  return res;
1812  }
1813 
1814  /** Compute the squared Euclidean norm of the array (sum of squares of the array elements).
1815  */
1816  typename NormTraits<MultiArrayView>::SquaredNormType
1817  squaredNorm() const
1818  {
1819  typedef typename NormTraits<MultiArrayView>::SquaredNormType SquaredNormType;
1820  SquaredNormType res = NumericTraits<SquaredNormType>::zero();
1821  detail::reduceOverMultiArray(traverser_begin(), shape(),
1822  res,
1823  detail::SquaredL2NormReduceFunctor(),
1824  MetaInt<actual_dimension-1>());
1825  return res;
1826  }
1827 
1828  /** Compute various norms of the array.
1829  The norm is determined by parameter \a type:
1830 
1831  <ul>
1832  <li> type == 0: maximum norm (L-infinity): maximum of absolute values of the array elements
1833  <li> type == 1: Manhattan norm (L1): sum of absolute values of the array elements
1834  <li> type == 2: Euclidean norm (L2): square root of <tt>squaredNorm()</tt> when \a useSquaredNorm is <tt>true</tt>,<br>
1835  or direct algorithm that avoids underflow/overflow otherwise.
1836  </ul>
1837 
1838  Parameter \a useSquaredNorm has no effect when \a type != 2. Defaults: compute L2 norm as square root of
1839  <tt>squaredNorm()</tt>.
1840  */
1841  typename NormTraits<MultiArrayView>::NormType
1842  norm(int type = 2, bool useSquaredNorm = true) const;
1843 
1844  /** return the pointer to the image data
1845  */
1846  pointer data () const
1847  {
1848  return m_ptr;
1849  }
1850 
1851  pointer & unsafePtr()
1852  {
1853  return m_ptr;
1854  }
1855 
1856  /**
1857  * returns true iff this view refers to valid data,
1858  * i.e. data() is not a NULL pointer. (this is false after
1859  * default construction.)
1860  */
1861  bool hasData () const
1862  {
1863  return m_ptr != 0;
1864  }
1865 
1866  /** returns a scan-order iterator pointing
1867  to the first array element.
1868  */
1869  iterator begin()
1870  {
1871  return iterator(*this);
1872  }
1873 
1874  /** returns a const scan-order iterator pointing
1875  to the first array element.
1876  */
1877  const_iterator begin() const
1878  {
1879  return const_iterator(*this);
1880  }
1881 
1882  /** returns a scan-order iterator pointing
1883  beyond the last array element.
1884  */
1885  iterator end()
1886  {
1887  return begin().getEndIterator();
1888  }
1889 
1890  /** returns a const scan-order iterator pointing
1891  beyond the last array element.
1892  */
1893  const_iterator end() const
1894  {
1895  return begin().getEndIterator();
1896  }
1897 
1898  /** returns the N-dimensional MultiIterator pointing
1899  to the first element in every dimension.
1900  */
1901  traverser traverser_begin ()
1902  {
1903  traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1904  return ret;
1905  }
1906 
1907  /** returns the N-dimensional MultiIterator pointing
1908  to the const first element in every dimension.
1909  */
1910  const_traverser traverser_begin () const
1911  {
1912  const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1913  return ret;
1914  }
1915 
1916  /** returns the N-dimensional MultiIterator pointing
1917  beyond the last element in dimension N, and to the
1918  first element in every other dimension.
1919  */
1920  traverser traverser_end ()
1921  {
1922  traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1923  ret += m_shape [actual_dimension-1];
1924  return ret;
1925  }
1926 
1927  /** returns the N-dimensional const MultiIterator pointing
1928  beyond the last element in dimension N, and to the
1929  first element in every other dimension.
1930  */
1931  const_traverser traverser_end () const
1932  {
1933  const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ());
1934  ret += m_shape [actual_dimension-1];
1935  return ret;
1936  }
1937 
1938  view_type view () const
1939  {
1940  return *this;
1941  }
1942 };
1943 
1944 template <unsigned int N, class T, class StrideTag>
1945 class MultiArrayView<N, Multiband<T>, StrideTag>
1946 : public MultiArrayView<N, T, StrideTag>
1947 {
1948  public:
1951  {}
1952 };
1953 
1954 
1955 template <unsigned int N, class T, class Stride1>
1956 template <class Stride2>
1957 void
1959 {
1960  if(m_ptr == 0)
1961  {
1962  vigra_precondition(rhs.checkInnerStride(Stride1()),
1963  "MultiArrayView<..., UnstridedArrayTag>::operator=(MultiArrayView const &): cannot create unstrided view from strided array.");
1964 
1965  m_shape = rhs.shape();
1966  m_stride = rhs.stride();
1967  m_ptr = rhs.data();
1968  }
1969  else
1970  {
1971  vigra_precondition(this->shape() == rhs.shape(),
1972  "MultiArrayView::operator=(MultiArrayView const &): shape mismatch.");
1973  this->copyImpl(rhs);
1974  }
1975 }
1976 
1977 template <unsigned int N, class T, class StrideTag>
1978 template <class CN>
1979 bool
1981 {
1982  vigra_precondition (shape () == rhs.shape (),
1983  "MultiArrayView::arraysOverlap(): shape mismatch.");
1984  const_pointer first_element = this->m_ptr,
1985  last_element = first_element + dot(this->m_shape - difference_type(1), this->m_stride);
1987  rhs_first_element = rhs.data(),
1988  rhs_last_element = rhs_first_element + dot(rhs.shape() - difference_type(1), rhs.stride());
1989  return !(last_element < rhs_first_element || rhs_last_element < first_element);
1990 }
1991 
1992 template <unsigned int N, class T, class StrideTag>
1993 template <class U, class CN>
1994 void
1996 {
1997  if(!arraysOverlap(rhs))
1998  {
1999  // no overlap -- can copy directly
2000  detail::copyMultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>());
2001  }
2002  else
2003  {
2004  // overlap: we got different views to the same data -- copy to intermediate memory in order to avoid
2005  // overwriting elements that are still needed on the rhs.
2006  MultiArray<N, T> tmp(rhs);
2007  detail::copyMultiArrayData(tmp.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>());
2008  }
2009 }
2010 
2011 #define VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(name, op) \
2012 template <unsigned int N, class T, class StrideTag> \
2013 template<class U, class C1> \
2014 MultiArrayView<N, T, StrideTag> & \
2015 MultiArrayView <N, T, StrideTag>::operator op(MultiArrayView<N, U, C1> const & rhs) \
2016 { \
2017  vigra_precondition(this->shape() == rhs.shape(), "MultiArrayView::operator" #op "() size mismatch."); \
2018  if(!arraysOverlap(rhs)) \
2019  { \
2020  detail::name##MultiArrayData(rhs.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>()); \
2021  } \
2022  else \
2023  { \
2024  MultiArray<N, T> tmp(rhs); \
2025  detail::name##MultiArrayData(tmp.traverser_begin(), shape(), traverser_begin(), MetaInt<actual_dimension-1>()); \
2026  } \
2027  return *this; \
2028 }
2029 
2030 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyAdd, +=)
2031 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copySub, -=)
2032 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyMul, *=)
2033 VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT(copyDiv, /=)
2034 
2035 #undef VIGRA_MULTI_ARRAY_COMPUTED_ASSIGNMENT
2036 
2037 template <unsigned int N, class T, class StrideTag>
2038 template <class U, class CN>
2039 void
2041 {
2042  vigra_precondition (shape () == rhs.shape (),
2043  "MultiArrayView::swapData(): shape mismatch.");
2044 
2045  // check for overlap of this and rhs
2046  const_pointer first_element = this->m_ptr,
2047  last_element = first_element + dot(this->m_shape - difference_type(1), this->m_stride);
2049  rhs_first_element = rhs.data(),
2050  rhs_last_element = rhs_first_element + dot(rhs.shape() - difference_type(1), rhs.stride());
2051  if(last_element < rhs_first_element || rhs_last_element < first_element)
2052  {
2053  // no overlap -- can swap directly
2054  detail::swapDataImpl(traverser_begin(), shape(), rhs.traverser_begin(), MetaInt<actual_dimension-1>());
2055  }
2056  else
2057  {
2058  // overlap: we got different views to the same data -- copy to intermediate memory in order to avoid
2059  // overwriting elements that are still needed.
2060  MultiArray<N, T> tmp(*this);
2061  copy(rhs);
2062  rhs.copy(tmp);
2063  }
2064 }
2065 
2066 template <unsigned int N, class T, class StrideTag>
2069 {
2070  difference_type shape, stride, check((typename difference_type::value_type)0);
2071  for (unsigned int i = 0; i < actual_dimension; ++i)
2072  {
2073  shape[i] = m_shape[s[i]];
2074  stride[i] = m_stride[s[i]];
2075  ++check[s[i]];
2076  }
2077  vigra_precondition(check == difference_type(1),
2078  "MultiArrayView::transpose(): every dimension must occur exactly once.");
2079  return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr);
2080 }
2081 
2082 template <unsigned int N, class T, class StrideTag>
2085 {
2086  difference_type permutation;
2087  for(int k=0; k<(int)N; ++k)
2088  permutation[k] = k;
2089  for(int k=0; k<(int)N-1; ++k)
2090  {
2091  int smallest = k;
2092  for(int j=k+1; j<(int)N; ++j)
2093  {
2094  if(stride[j] < stride[smallest])
2095  smallest = j;
2096  }
2097  if(smallest != k)
2098  {
2099  std::swap(stride[k], stride[smallest]);
2100  std::swap(permutation[k], permutation[smallest]);
2101  }
2102  }
2103  difference_type ordering;
2104  for(unsigned int k=0; k<N; ++k)
2105  ordering[permutation[k]] = k;
2106  return ordering;
2107 }
2108 
2109 template <unsigned int N, class T, class StrideTag>
2112 {
2113  difference_type ordering(strideOrdering(m_stride)), permutation;
2114  for(MultiArrayIndex k=0; k<N; ++k)
2115  permutation[ordering[k]] = k;
2116  return permuteDimensions(permutation);
2117 }
2118 
2119 template <unsigned int N, class T, class StrideTag>
2122 {
2123  difference_type ordering(strideOrdering(m_stride)), permutation;
2124  for(MultiArrayIndex k=0; k<N; ++k)
2125  permutation[N-1-ordering[k]] = k;
2126  return permuteDimensions(permutation);
2127 }
2128 
2129 template <unsigned int N, class T, class StrideTag>
2130 template <int M, class Index>
2131 MultiArrayView <N-M, T, StrideTag>
2133 {
2135  stride.init (m_stride.begin () + N-M, m_stride.end ());
2136  pointer ptr = m_ptr + dot (d, stride);
2137  static const int NNew = (N-M == 0) ? 1 : N-M;
2138  TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride;
2139  if (N-M == 0)
2140  {
2141  inner_shape [0] = 1;
2142  inner_stride [0] = 1;
2143  }
2144  else
2145  {
2146  inner_shape.init (m_shape.begin (), m_shape.end () - M);
2147  inner_stride.init (m_stride.begin (), m_stride.end () - M);
2148  }
2149  return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, ptr);
2150 }
2151 
2152 template <unsigned int N, class T, class StrideTag>
2153 template <int M, class Index>
2154 MultiArrayView <N - M, T, StridedArrayTag>
2156 {
2158  stride.init (m_stride.begin (), m_stride.end () - N + M);
2159  pointer ptr = m_ptr + dot (d, stride);
2160  static const int NNew = (N-M == 0) ? 1 : N-M;
2161  TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride;
2162  if (N-M == 0)
2163  {
2164  outer_shape [0] = 1;
2165  outer_stride [0] = 1;
2166  }
2167  else
2168  {
2169  outer_shape.init (m_shape.begin () + M, m_shape.end ());
2170  outer_stride.init (m_stride.begin () + M, m_stride.end ());
2171  }
2172  return MultiArrayView <N-M, T, StridedArrayTag>
2173  (outer_shape, outer_stride, ptr);
2174 }
2175 
2176 template <unsigned int N, class T, class StrideTag>
2177 template <unsigned int M>
2178 MultiArrayView <N-1, T, typename detail::MaybeStrided<StrideTag, M>::type >
2180 {
2181  static const int NNew = (N-1 == 0) ? 1 : N-1;
2182  TinyVector <MultiArrayIndex, NNew> shape, stride;
2183  // the remaining dimensions are 0..n-1,n+1..N-1
2184  if (N-1 == 0)
2185  {
2186  shape[0] = 1;
2187  stride[0] = 1;
2188  }
2189  else
2190  {
2191  std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ());
2192  std::copy (m_shape.begin () + M+1, m_shape.end (),
2193  shape.begin () + M);
2194  std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin ());
2195  std::copy (m_stride.begin () + M+1, m_stride.end (),
2196  stride.begin () + M);
2197  }
2198  return MultiArrayView <N-1, T, typename detail::MaybeStrided<StrideTag, M>::type>
2199  (shape, stride, m_ptr + d * m_stride[M]);
2200 }
2201 
2202 template <unsigned int N, class T, class StrideTag>
2203 MultiArrayView <N - 1, T, StrideTag>
2205 {
2206  static const int NNew = (N-1 == 0) ? 1 : N-1;
2207  TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride;
2208  if (N-1 == 0)
2209  {
2210  inner_shape [0] = 1;
2211  inner_stride [0] = 1;
2212  }
2213  else
2214  {
2215  inner_shape.init (m_shape.begin (), m_shape.end () - 1);
2216  inner_stride.init (m_stride.begin (), m_stride.end () - 1);
2217  }
2218  return MultiArrayView <N-1, T, StrideTag> (inner_shape, inner_stride,
2219  m_ptr + d * m_stride [N-1]);
2220 }
2221 
2222 template <unsigned int N, class T, class StrideTag>
2223 MultiArrayView <N - 1, T, StridedArrayTag>
2225 {
2226  static const int NNew = (N-1 == 0) ? 1 : N-1;
2227  TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride;
2228  if (N-1 == 0)
2229  {
2230  outer_shape [0] = 1;
2231  outer_stride [0] = 1;
2232  }
2233  else
2234  {
2235  outer_shape.init (m_shape.begin () + 1, m_shape.end ());
2236  outer_stride.init (m_stride.begin () + 1, m_stride.end ());
2237  }
2238  return MultiArrayView <N-1, T, StridedArrayTag>
2239  (outer_shape, outer_stride, m_ptr + d * m_stride [0]);
2240 }
2241 
2242 template <unsigned int N, class T, class StrideTag>
2243 MultiArrayView <N - 1, T, StridedArrayTag>
2245 {
2246  vigra_precondition (
2247  n < static_cast <int> (N),
2248  "MultiArrayView <N, T, StrideTag>::bindAt(): dimension out of range.");
2249  static const int NNew = (N-1 == 0) ? 1 : N-1;
2250  TinyVector <MultiArrayIndex, NNew> shape, stride;
2251  // the remaining dimensions are 0..n-1,n+1..N-1
2252  if (N-1 == 0)
2253  {
2254  shape [0] = 1;
2255  stride [0] = 1;
2256  }
2257  else
2258  {
2259  std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ());
2260  std::copy (m_shape.begin () + n+1, m_shape.end (),
2261  shape.begin () + n);
2262  std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin ());
2263  std::copy (m_stride.begin () + n+1, m_stride.end (),
2264  stride.begin () + n);
2265  }
2266  return MultiArrayView <N-1, T, StridedArrayTag>
2267  (shape, stride, m_ptr + d * m_stride[n]);
2268 }
2269 
2270 
2271 template <unsigned int N, class T, class StrideTag>
2274 {
2275  vigra_precondition(0 <= d && d <= static_cast <difference_type_1> (N),
2276  "MultiArrayView<N, ...>::expandElements(d): 0 <= 'd' <= N required.");
2277 
2278  int elementSize = ExpandElementResult<T>::size;
2279  typename MultiArrayShape<N+1>::type newShape, newStrides;
2280  for(int k=0; k<d; ++k)
2281  {
2282  newShape[k] = m_shape[k];
2283  newStrides[k] = m_stride[k]*elementSize;
2284  }
2285 
2286  newShape[d] = elementSize;
2287  newStrides[d] = 1;
2288 
2289  for(int k=d; k<N; ++k)
2290  {
2291  newShape[k+1] = m_shape[k];
2292  newStrides[k+1] = m_stride[k]*elementSize;
2293  }
2294 
2295  typedef typename ExpandElementResult<T>::type U;
2297  newShape, newStrides, reinterpret_cast<U*>(m_ptr));
2298 }
2299 
2300 template <unsigned int N, class T, class StrideTag>
2303 {
2304  vigra_precondition (
2305  0 <= i && i <= static_cast <difference_type_1> (N),
2306  "MultiArrayView <N, T, StrideTag>::insertSingletonDimension(): index out of range.");
2307  TinyVector <MultiArrayIndex, N+1> shape, stride;
2308  std::copy (m_shape.begin (), m_shape.begin () + i, shape.begin ());
2309  std::copy (m_shape.begin () + i, m_shape.end (), shape.begin () + i + 1);
2310  std::copy (m_stride.begin (), m_stride.begin () + i, stride.begin ());
2311  std::copy (m_stride.begin () + i, m_stride.end (), stride.begin () + i + 1);
2312  shape[i] = 1;
2313  stride[i] = 1;
2314 
2315  return MultiArrayView <N+1, T, StrideTag>(shape, stride, m_ptr);
2316 }
2317 
2318 template <unsigned int N, class T, class StrideTag>
2319 typename NormTraits<MultiArrayView <N, T, StrideTag> >::NormType
2320 MultiArrayView <N, T, StrideTag>::norm(int type, bool useSquaredNorm) const
2321 {
2322  typedef typename NormTraits<MultiArrayView>::NormType NormType;
2323 
2324  switch(type)
2325  {
2326  case 0:
2327  {
2328  NormType res = NumericTraits<NormType>::zero();
2329  detail::reduceOverMultiArray(traverser_begin(), shape(),
2330  res,
2331  detail::MaxNormReduceFunctor(),
2332  MetaInt<actual_dimension-1>());
2333  return res;
2334  }
2335  case 1:
2336  {
2337  NormType res = NumericTraits<NormType>::zero();
2338  detail::reduceOverMultiArray(traverser_begin(), shape(),
2339  res,
2340  detail::L1NormReduceFunctor(),
2341  MetaInt<actual_dimension-1>());
2342  return res;
2343  }
2344  case 2:
2345  {
2346  if(useSquaredNorm)
2347  {
2348  return sqrt((NormType)squaredNorm());
2349  }
2350  else
2351  {
2352  NormType normMax = NumericTraits<NormType>::zero();
2353  detail::reduceOverMultiArray(traverser_begin(), shape(),
2354  normMax,
2355  detail::MaxNormReduceFunctor(),
2356  MetaInt<actual_dimension-1>());
2357  if(normMax == NumericTraits<NormType>::zero())
2358  return normMax;
2359  NormType res = NumericTraits<NormType>::zero();
2360  detail::reduceOverMultiArray(traverser_begin(), shape(),
2361  res,
2362  detail::WeightedL2NormReduceFunctor<NormType>(1.0/normMax),
2363  MetaInt<actual_dimension-1>());
2364  return sqrt(res)*normMax;
2365  }
2366  }
2367  default:
2368  vigra_precondition(false, "MultiArrayView::norm(): Unknown norm type.");
2369  return NumericTraits<NormType>::zero(); // unreachable
2370  }
2371 }
2372 
2373 
2374 /********************************************************/
2375 /* */
2376 /* norm */
2377 /* */
2378 /********************************************************/
2379 
2380 template <unsigned int N, class T, class StrideTag>
2381 inline typename NormTraits<MultiArrayView <N, T, StrideTag> >::SquaredNormType
2383 {
2384  return a.squaredNorm();
2385 }
2386 
2387 template <unsigned int N, class T, class StrideTag>
2388 inline typename NormTraits<MultiArrayView <N, T, StrideTag> >::NormType
2390 {
2391  return a.norm();
2392 }
2393 
2394 /********************************************************/
2395 /* */
2396 /* MultiArray */
2397 /* */
2398 /********************************************************/
2399 
2400 /** \brief Main <TT>MultiArray</TT> class containing the memory
2401  management.
2402 
2403 This class inherits the interface of MultiArrayView, and implements
2404 the memory ownership.
2405 MultiArray's are always unstrided, striding them creates a MultiArrayView.
2406 
2407 
2408 The template parameters are as follows
2409 \code
2410  N: the array dimension
2411 
2412  T: the type of the array elements
2413 
2414  A: the allocator used for internal storage management
2415  (default: std::allocator<T>)
2416 \endcode
2417 
2418 <b>\#include</b> <vigra/multi_array.hxx> <br/>
2419 Namespace: vigra
2420 */
2421 template <unsigned int N, class T, class A /* default already declared above */>
2423 : public MultiArrayView <N, typename vigra::detail::ResolveMultiband<T>::type,
2424  typename vigra::detail::ResolveMultiband<T>::Stride>
2425 {
2426  public:
2428 
2429  /** the view type associated with this array.
2430  */
2433 
2434  using view_type::actual_dimension;
2435 
2436  /** the allocator type used to allocate the memory
2437  */
2438  typedef A allocator_type;
2439 
2440  /** the matrix type associated with this array.
2441  */
2443 
2444  /** the array's value type
2445  */
2447 
2448  /** pointer type
2449  */
2450  typedef typename view_type::pointer pointer;
2451 
2452  /** const pointer type
2453  */
2455 
2456  /** reference type (result of operator[])
2457  */
2459 
2460  /** const reference type (result of operator[] const)
2461  */
2463 
2464  /** size type
2465  */
2467 
2468  /** difference type (used for multi-dimensional offsets and indices)
2469  */
2471 
2472  /** difference and index type for a single dimension
2473  */
2475 
2476  /** traverser type
2477  */
2479 
2480  /** traverser type to const data
2481  */
2483 
2484  // /** sequential (random access) iterator type
2485  // */
2486  // typedef typename vigra::detail::MultiIteratorChooser<actual_stride>::template Iterator<N, value_type, reference, pointer>::type
2487  // iterator;
2488 
2489  // /** sequential (random access) const iterator type
2490  // */
2491  // typedef typename vigra::detail::MultiIteratorChooser<actual_stride>::template Iterator<N, value_type, const_reference, const_pointer>::type
2492  // const_iterator;
2493 
2494  /** sequential (random access) iterator type
2495  */
2496  typedef typename view_type::iterator iterator;
2497 
2498  /** sequential (random access) const iterator type
2499  */
2501 
2502 protected:
2503 
2504  typedef typename difference_type::value_type diff_zero_t;
2505 
2506  /** the allocator used to allocate the memory
2507  */
2508  allocator_type m_alloc;
2509 
2510  /** allocate memory for s pixels, write its address into the given
2511  pointer and initialize the pixels with init.
2512  */
2513  void allocate (pointer &ptr, difference_type_1 s, const_reference init);
2514 
2515  /** allocate memory for s pixels, write its address into the given
2516  pointer and initialize the linearized pixels to the values of init.
2517  */
2518  template <class U>
2519  void allocate (pointer &ptr, difference_type_1 s, U const * init);
2520 
2521  /** allocate memory, write its address into the given
2522  pointer and initialize it by copying the data from the given MultiArrayView.
2523  */
2524  template <class U, class StrideTag>
2525  void allocate (pointer &ptr, MultiArrayView<N, U, StrideTag> const & init);
2526 
2527  /** deallocate the memory (of length s) starting at the given address.
2528  */
2529  void deallocate (pointer &ptr, difference_type_1 s);
2530 
2531  template <class U, class StrideTag>
2532  void copyOrReshape (const MultiArrayView<N, U, StrideTag> &rhs);
2533 public:
2534  /** default constructor
2535  */
2537  : view_type (difference_type (diff_zero_t(0)),
2538  difference_type (diff_zero_t(0)), 0)
2539  {}
2540 
2541  /** construct with given allocator
2542  */
2543  MultiArray (allocator_type const & alloc)
2544  : view_type(difference_type (diff_zero_t(0)),
2545  difference_type (diff_zero_t(0)), 0),
2546  m_alloc(alloc)
2547  {}
2548 
2549  /** construct with given length
2550 
2551  Use only for 1-dimensional arrays (<tt>N==1</tt>).
2552  */
2553  explicit MultiArray (difference_type_1 length,
2554  allocator_type const & alloc = allocator_type());
2555 
2556 
2557  /** construct with given width and height
2558 
2559  Use only for 2-dimensional arrays (<tt>N==2</tt>).
2560  */
2561  MultiArray (difference_type_1 width, difference_type_1 height,
2562  allocator_type const & alloc = allocator_type());
2563 
2564  /** construct with given shape
2565  */
2566  explicit MultiArray (const difference_type &shape,
2567  allocator_type const & alloc = allocator_type());
2568 
2569  /** construct from shape with an initial value
2570  */
2571  MultiArray (const difference_type &shape, const_reference init,
2572  allocator_type const & alloc = allocator_type());
2573 
2574  /** construct from shape and initialize with a linear sequence in scan order
2575  (i.e. first pixel gets value 0, second on gets value 1 and so on).
2576  */
2577  MultiArray (const difference_type &shape, MultiArrayInitializationTag init,
2578  allocator_type const & alloc = allocator_type());
2579 
2580  /** construct from shape and copy values from the given array
2581  */
2582  MultiArray (const difference_type &shape, const_pointer init,
2583  allocator_type const & alloc = allocator_type());
2584 
2585  /** copy constructor
2586  */
2587  MultiArray (const MultiArray &rhs)
2588  : view_type(rhs.m_shape, rhs.m_stride, 0),
2589  m_alloc (rhs.m_alloc)
2590  {
2591  allocate (this->m_ptr, this->elementCount (), rhs.data ());
2592  }
2593 
2594  /** constructor from an array expression
2595  */
2596  template<class Expression>
2597  MultiArray (multi_math::MultiMathOperand<Expression> const & rhs,
2598  allocator_type const & alloc = allocator_type())
2599  : view_type(difference_type (diff_zero_t(0)),
2600  difference_type (diff_zero_t(0)), 0),
2601  m_alloc (alloc)
2602  {
2603  multi_math::math_detail::assignOrResize(*this, rhs);
2604  }
2605 
2606  /** construct by copying from a MultiArrayView
2607  */
2608  template <class U, class StrideTag>
2610  allocator_type const & alloc = allocator_type());
2611 
2612  /** assignment.<br>
2613  If the size of \a rhs is the same as the left-hand side arrays's old size, only
2614  the data are copied. Otherwise, new storage is allocated, which invalidates all
2615  objects (array views, iterators) depending on the lhs array.
2616  */
2617  MultiArray & operator= (const MultiArray &rhs)
2618  {
2619  if (this != &rhs)
2620  this->copyOrReshape(rhs);
2621  return *this;
2622  }
2623 
2624  /** assignment from arbitrary MultiArrayView.<br>
2625  If the size of \a rhs is the same as the left-hand side arrays's old size, only
2626  the data are copied. Otherwise, new storage is allocated, which invalidates all
2627  objects (array views, iterators) depending on the lhs array.
2628  */
2629  template <class U, class StrideTag>
2630  MultiArray &operator= (const MultiArrayView<N, U, StrideTag> &rhs)
2631  {
2632  this->copyOrReshape(rhs);
2633  return *this;
2634  }
2635 
2636  /** assignment from scalar.<br>
2637  Equivalent to MultiArray::init(v).
2638  */
2639  MultiArray & operator=(value_type const & v)
2640  {
2641  return this->init(v);
2642  }
2643 
2644  /** Add-assignment from arbitrary MultiArrayView. Fails with
2645  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2646  If the left array has no data (hasData() is false), this function is
2647  equivalent to a normal assignment (i.e. an empty
2648  array is interpreted as a zero-array of appropriate size).
2649  */
2650  template <class U, class StrideTag>
2652  {
2653  if(this->hasData())
2654  view_type::operator+=(rhs);
2655  else
2656  *this = rhs;
2657  return *this;
2658  }
2659 
2660  /** Subtract-assignment from arbitrary MultiArrayView. Fails with
2661  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2662  If the left array has no data (hasData() is false), this function is
2663  equivalent to an assignment of the negated rhs (i.e. an empty
2664  array is interpreted as a zero-array of appropriate size).
2665  */
2666  template <class U, class StrideTag>
2668  {
2669  if(!this->hasData())
2670  this->reshape(rhs.shape());
2671  view_type::operator-=(rhs);
2672  return *this;
2673  }
2674 
2675  /** Multiply-assignment from arbitrary MultiArrayView. Fails with
2676  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2677  If the left array has no data (hasData() is false), this function is
2678  equivalent to reshape(rhs.shape()) with zero initialisation (i.e. an empty
2679  array is interpreted as a zero-array of appropriate size).
2680  */
2681  template <class U, class StrideTag>
2683  {
2684  if(this->hasData())
2685  view_type::operator*=(rhs);
2686  else
2687  this->reshape(rhs.shape());
2688  return *this;
2689  }
2690 
2691  /** Divide-assignment from arbitrary MultiArrayView. Fails with
2692  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2693  If the left array has no data (hasData() is false), this function is
2694  equivalent to reshape(rhs.shape()) with zero initialisation (i.e. an empty
2695  array is interpreted as a zero-array of appropriate size).
2696  */
2697  template <class U, class StrideTag>
2699  {
2700  if(this->hasData())
2701  view_type::operator/=(rhs);
2702  else
2703  this->reshape(rhs.shape());
2704  return *this;
2705  }
2706 
2707  /** Add-assignment of a scalar.
2708  */
2709  MultiArray &operator+= (const T &rhs)
2710  {
2711  view_type::operator+=(rhs);
2712  return *this;
2713  }
2714 
2715  /** Subtract-assignment of a scalar.
2716  */
2717  MultiArray &operator-= (const T &rhs)
2718  {
2719  view_type::operator-=(rhs);
2720  return *this;
2721  }
2722 
2723  /** Multiply-assignment of a scalar.
2724  */
2725  MultiArray &operator*= (const T &rhs)
2726  {
2727  view_type::operator*=(rhs);
2728  return *this;
2729  }
2730 
2731  /** Divide-assignment of a scalar.
2732  */
2733  MultiArray &operator/= (const T &rhs)
2734  {
2735  view_type::operator/=(rhs);
2736  return *this;
2737  }
2738  /** Assignment of an array expression. Fails with
2739  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2740  */
2741  template<class Expression>
2742  MultiArray & operator=(multi_math::MultiMathOperand<Expression> const & rhs)
2743  {
2744  multi_math::math_detail::assignOrResize(*this, rhs);
2745  return *this;
2746  }
2747 
2748  /** Add-assignment of an array expression. Fails with
2749  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2750  */
2751  template<class Expression>
2752  MultiArray & operator+=(multi_math::MultiMathOperand<Expression> const & rhs)
2753  {
2754  multi_math::math_detail::plusAssignOrResize(*this, rhs);
2755  return *this;
2756  }
2757 
2758  /** Subtract-assignment of an array expression. Fails with
2759  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2760  */
2761  template<class Expression>
2762  MultiArray & operator-=(multi_math::MultiMathOperand<Expression> const & rhs)
2763  {
2764  multi_math::math_detail::minusAssignOrResize(*this, rhs);
2765  return *this;
2766  }
2767 
2768  /** Multiply-assignment of an array expression. Fails with
2769  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2770  */
2771  template<class Expression>
2772  MultiArray & operator*=(multi_math::MultiMathOperand<Expression> const & rhs)
2773  {
2774  multi_math::math_detail::multiplyAssignOrResize(*this, rhs);
2775  return *this;
2776  }
2777 
2778  /** Divide-assignment of an array expression. Fails with
2779  <tt>PreconditionViolation</tt> exception when the shapes do not match.
2780  */
2781  template<class Expression>
2782  MultiArray & operator/=(multi_math::MultiMathOperand<Expression> const & rhs)
2783  {
2784  multi_math::math_detail::divideAssignOrResize(*this, rhs);
2785  return *this;
2786  }
2787 
2788  /** destructor
2789  */
2791  {
2792  deallocate (this->m_ptr, this->elementCount ());
2793  }
2794 
2795 
2796  /** init elements with a constant
2797  */
2798  template <class U>
2799  MultiArray & init(const U & init)
2800  {
2801  view_type::init(init);
2802  return *this;
2803  }
2804 
2805  /** Allocate new memory with the given shape and initialize with zeros.<br>
2806  <em>Note:</em> this operation invalidates all dependent objects
2807  (array views and iterators)
2808  */
2809  void reshape (const difference_type &shape)
2810  {
2811  reshape (shape, value_type());
2812  }
2813 
2814  /** Allocate new memory with the given shape and initialize it
2815  with the given value.<br>
2816  <em>Note:</em> this operation invalidates all dependent objects
2817  (array views and iterators)
2818  */
2819  void reshape (const difference_type &shape, const_reference init);
2820 
2821  /** Swap the contents with another MultiArray. This is fast,
2822  because no data are copied, but only pointers and shapes swapped.
2823  <em>Note:</em> this operation invalidates all dependent objects
2824  (array views and iterators)
2825  */
2826  void swap (MultiArray & other);
2827 
2828  // /** sequential iterator pointing to the first array element.
2829  // */
2830  // iterator begin ()
2831  // {
2832  // return vigra::detail::MultiIteratorChooser<actual_stride>::template constructIterator<iterator>((view_type *)this);
2833  // }
2834 
2835  // /** sequential iterator pointing beyond the last array element.
2836  // */
2837  // iterator end ()
2838  // {
2839  // return begin() + this->elementCount();
2840  // }
2841 
2842  // /** sequential const iterator pointing to the first array element.
2843  // */
2844  // const_iterator begin () const
2845  // {
2846  // return vigra::detail::MultiIteratorChooser<actual_stride>::template constructIterator<iterator>((view_type const *)this);
2847  // }
2848 
2849  // /** sequential const iterator pointing beyond the last array element.
2850  // */
2851  // const_iterator end () const
2852  // {
2853  // return begin() + this->elementCount();
2854  // }
2855 
2856  /** get the allocator.
2857  */
2858  allocator_type const & allocator () const
2859  {
2860  return m_alloc;
2861  }
2862 
2863  static difference_type defaultStride(difference_type const & shape)
2864  {
2865  return vigra::detail::ResolveMultiband<T>::defaultStride(shape);
2866  }
2867 };
2868 
2869 template <unsigned int N, class T, class A>
2870 MultiArray <N, T, A>::MultiArray (difference_type_1 length,
2871  allocator_type const & alloc)
2872 : view_type(difference_type(length),
2873  defaultStride(difference_type(length)),
2874  0),
2875  m_alloc(alloc)
2876 {
2877  allocate (this->m_ptr, this->elementCount (), value_type());
2878 }
2879 
2880 template <unsigned int N, class T, class A>
2881 MultiArray <N, T, A>::MultiArray (difference_type_1 width, difference_type_1 height,
2882  allocator_type const & alloc)
2883 : view_type(difference_type(width, height),
2884  defaultStride(difference_type(width, height)),
2885  0),
2886  m_alloc(alloc)
2887 {
2888  allocate (this->m_ptr, this->elementCount (), value_type());
2889 }
2890 
2891 template <unsigned int N, class T, class A>
2892 MultiArray <N, T, A>::MultiArray (const difference_type &shape,
2893  allocator_type const & alloc)
2894 : view_type(shape,
2895  defaultStride(shape),
2896  0),
2897  m_alloc(alloc)
2898 {
2899  if (N == 0)
2900  {
2901  this->m_shape [0] = 1;
2902  this->m_stride [0] = 1;
2903  }
2904  allocate (this->m_ptr, this->elementCount (), value_type());
2905 }
2906 
2907 template <unsigned int N, class T, class A>
2908 MultiArray <N, T, A>::MultiArray (const difference_type &shape, const_reference init,
2909  allocator_type const & alloc)
2910 : view_type(shape,
2911  defaultStride(shape),
2912  0),
2913  m_alloc(alloc)
2914 {
2915  if (N == 0)
2916  {
2917  this->m_shape [0] = 1;
2918  this->m_stride [0] = 1;
2919  }
2920  allocate (this->m_ptr, this->elementCount (), init);
2921 }
2922 
2923 template <unsigned int N, class T, class A>
2925  allocator_type const & alloc)
2926 : view_type(shape,
2927  defaultStride(shape),
2928  0),
2929  m_alloc(alloc)
2930 {
2931  if (N == 0)
2932  {
2933  this->m_shape [0] = 1;
2934  this->m_stride [0] = 1;
2935  }
2936  allocate (this->m_ptr, this->elementCount (), value_type());
2937  switch(init)
2938  {
2939  case LinearSequence:
2940  linearSequence(this->begin(), this->end());
2941  break;
2942  default:
2943  vigra_precondition(false,
2944  "MultiArray(): invalid MultiArrayInitializationTag.");
2945  }
2946 }
2947 
2948 template <unsigned int N, class T, class A>
2949 MultiArray <N, T, A>::MultiArray (const difference_type &shape, const_pointer init,
2950  allocator_type const & alloc)
2951 : view_type(shape,
2952  defaultStride(shape),
2953  0),
2954  m_alloc(alloc)
2955 {
2956  if (N == 0)
2957  {
2958  this->m_shape [0] = 1;
2959  this->m_stride [0] = 1;
2960  }
2961  allocate (this->m_ptr, this->elementCount (), init);
2962 }
2963 
2964 template <unsigned int N, class T, class A>
2965 template <class U, class StrideTag>
2967  allocator_type const & alloc)
2968 : view_type(rhs.shape(),
2969  defaultStride(rhs.shape()),
2970  0),
2971  m_alloc (alloc)
2972 {
2973  allocate (this->m_ptr, rhs);
2974 }
2975 
2976 template <unsigned int N, class T, class A>
2977 template <class U, class StrideTag>
2978 void
2980 {
2981  if (this->shape() == rhs.shape())
2982  this->copy(rhs);
2983  else
2984  {
2985  MultiArray t(rhs);
2986  this->swap(t);
2987  }
2988 }
2989 
2990 template <unsigned int N, class T, class A>
2991 void MultiArray <N, T, A>::reshape (const difference_type & new_shape,
2992  const_reference initial)
2993 {
2994  if (N == 0)
2995  {
2996  return;
2997  }
2998  else if(new_shape == this->shape())
2999  {
3000  this->init(initial);
3001  }
3002  else
3003  {
3004  difference_type new_stride = defaultStride(new_shape);
3005  difference_type_1 new_size = prod(new_shape);
3006  pointer new_ptr = pointer();
3007  allocate (new_ptr, new_size, initial);
3008  deallocate (this->m_ptr, this->elementCount ());
3009  this->m_ptr = new_ptr;
3010  this->m_shape = new_shape;
3011  this->m_stride = new_stride;
3012  }
3013 }
3014 
3015 
3016 template <unsigned int N, class T, class A>
3017 inline void
3019 {
3020  if (this == &other)
3021  return;
3022  this->view_type::swap(other);
3023  std::swap(this->m_alloc, other.m_alloc);
3024 }
3025 
3026 template <unsigned int N, class T, class A>
3027 void MultiArray <N, T, A>::allocate (pointer & ptr, difference_type_1 s,
3028  const_reference init)
3029 {
3030  if(s == 0)
3031  {
3032  ptr = 0;
3033  return;
3034  }
3035  ptr = m_alloc.allocate ((typename A::size_type)s);
3036  difference_type_1 i = 0;
3037  try {
3038  for (; i < s; ++i)
3039  m_alloc.construct (ptr + i, init);
3040  }
3041  catch (...) {
3042  for (difference_type_1 j = 0; j < i; ++j)
3043  m_alloc.destroy (ptr + j);
3044  m_alloc.deallocate (ptr, (typename A::size_type)s);
3045  throw;
3046  }
3047 }
3048 
3049 template <unsigned int N, class T, class A>
3050 template <class U>
3051 void MultiArray <N, T, A>::allocate (pointer & ptr, difference_type_1 s,
3052  U const * init)
3053 {
3054  if(s == 0)
3055  {
3056  ptr = 0;
3057  return;
3058  }
3059  ptr = m_alloc.allocate ((typename A::size_type)s);
3060  difference_type_1 i = 0;
3061  try {
3062  for (; i < s; ++i, ++init)
3063  m_alloc.construct (ptr + i, *init);
3064  }
3065  catch (...) {
3066  for (difference_type_1 j = 0; j < i; ++j)
3067  m_alloc.destroy (ptr + j);
3068  m_alloc.deallocate (ptr, (typename A::size_type)s);
3069  throw;
3070  }
3071 }
3072 
3073 template <unsigned int N, class T, class A>
3074 template <class U, class StrideTag>
3076 {
3077  difference_type_1 s = init.elementCount();
3078  if(s == 0)
3079  {
3080  ptr = 0;
3081  return;
3082  }
3083  ptr = m_alloc.allocate ((typename A::size_type)s);
3084  pointer p = ptr;
3085  try {
3086  detail::uninitializedCopyMultiArrayData(init.traverser_begin(), init.shape(),
3087  p, m_alloc, MetaInt<actual_dimension-1>());
3088  }
3089  catch (...) {
3090  for (pointer pp = ptr; pp < p; ++pp)
3091  m_alloc.destroy (pp);
3092  m_alloc.deallocate (ptr, (typename A::size_type)s);
3093  throw;
3094  }
3095 }
3096 
3097 template <unsigned int N, class T, class A>
3098 inline void MultiArray <N, T, A>::deallocate (pointer & ptr, difference_type_1 s)
3099 {
3100  if (ptr == 0)
3101  return;
3102  for (difference_type_1 i = 0; i < s; ++i)
3103  m_alloc.destroy (ptr + i);
3104  m_alloc.deallocate (ptr, (typename A::size_type)s);
3105  ptr = 0;
3106 }
3107 
3108 /********************************************************/
3109 /* */
3110 /* argument object factories */
3111 /* */
3112 /********************************************************/
3113 
3114 template <unsigned int N, class T, class StrideTag>
3115 inline triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3118 srcMultiArrayRange( MultiArrayView<N,T,StrideTag> const & array )
3119 {
3120  return triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3121  typename MultiArrayView<N,T,StrideTag>::difference_type,
3123  ( array.traverser_begin(),
3124  array.shape(),
3126 }
3127 
3128 template <unsigned int N, class T, class StrideTag, class Accessor>
3129 inline triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3130  typename MultiArrayView<N,T,StrideTag>::difference_type,
3131  Accessor >
3132 srcMultiArrayRange( MultiArrayView<N,T,StrideTag> const & array, Accessor a )
3133 {
3134  return triple<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3135  typename MultiArrayView<N,T,StrideTag>::difference_type,
3136  Accessor >
3137  ( array.traverser_begin(),
3138  array.shape(),
3139  a);
3140 }
3141 
3142 template <unsigned int N, class T, class StrideTag>
3143 inline pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3145 srcMultiArray( MultiArrayView<N,T,StrideTag> const & array )
3146 {
3147  return pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3149  ( array.traverser_begin(),
3151 }
3152 
3153 template <unsigned int N, class T, class StrideTag, class Accessor>
3154 inline pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3155  Accessor >
3156 srcMultiArray( MultiArrayView<N,T,StrideTag> const & array, Accessor a )
3157 {
3158  return pair<typename MultiArrayView<N,T,StrideTag>::const_traverser,
3159  Accessor >
3160  ( array.traverser_begin(), a );
3161 }
3162 
3163 template <unsigned int N, class T, class StrideTag>
3164 inline triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3165  typename MultiArrayView<N,T,StrideTag>::difference_type,
3167 destMultiArrayRange( MultiArrayView<N,T,StrideTag> & array )
3168 {
3169  return triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3170  typename MultiArrayView<N,T,StrideTag>::difference_type,
3172  ( array.traverser_begin(),
3173  array.shape(),
3175 }
3176 
3177 template <unsigned int N, class T, class StrideTag, class Accessor>
3178 inline triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3179  typename MultiArrayView<N,T,StrideTag>::difference_type,
3180  Accessor >
3181 destMultiArrayRange( MultiArrayView<N,T,StrideTag> & array, Accessor a )
3182 {
3183  return triple<typename MultiArrayView<N,T,StrideTag>::traverser,
3184  typename MultiArrayView<N,T,StrideTag>::difference_type,
3185  Accessor >
3186  ( array.traverser_begin(),
3187  array.shape(),
3188  a );
3189 }
3190 
3191 template <unsigned int N, class T, class StrideTag>
3192 inline pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3194 destMultiArray( MultiArrayView<N,T,StrideTag> & array )
3195 {
3196  return pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3198  ( array.traverser_begin(),
3200 }
3201 
3202 template <unsigned int N, class T, class StrideTag, class Accessor>
3203 inline pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3204  Accessor >
3205 destMultiArray( MultiArrayView<N,T,StrideTag> & array, Accessor a )
3206 {
3207  return pair<typename MultiArrayView<N,T,StrideTag>::traverser,
3208  Accessor >
3209  ( array.traverser_begin(), a );
3210 }
3211 
3212 /********************************************************************/
3213 
3214 template <class PixelType, class Accessor>
3215 inline triple<ConstStridedImageIterator<PixelType>,
3217 srcImageRange(const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3218 {
3219  ConstStridedImageIterator<PixelType>
3220  ul(img.data(), 1, img.stride(0), img.stride(1));
3221  return triple<ConstStridedImageIterator<PixelType>,
3222  ConstStridedImageIterator<PixelType>,
3223  Accessor>(
3224  ul, ul + Size2D(img.shape(0), img.shape(1)), a);
3225 }
3226 
3227 template <class PixelType, class Accessor>
3228 inline pair<ConstStridedImageIterator<PixelType>, Accessor>
3229 srcImage(const MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3230 {
3231  ConstStridedImageIterator<PixelType>
3232  ul(img.data(), 1, img.stride(0), img.stride(1));
3233  return pair<ConstStridedImageIterator<PixelType>, Accessor>
3234  (ul, a);
3235 }
3236 
3237 template <class PixelType, class Accessor>
3238 inline triple<StridedImageIterator<PixelType>,
3240 destImageRange(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3241 {
3242  StridedImageIterator<PixelType>
3243  ul(img.data(), 1, img.stride(0), img.stride(1));
3244  return triple<StridedImageIterator<PixelType>,
3245  StridedImageIterator<PixelType>,
3246  Accessor>(
3247  ul, ul + Size2D(img.shape(0), img.shape(1)), a);
3248 }
3249 
3250 template <class PixelType, class Accessor>
3251 inline pair<StridedImageIterator<PixelType>, Accessor>
3252 destImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3253 {
3254  StridedImageIterator<PixelType>
3255  ul(img.data(), 1, img.stride(0), img.stride(1));
3256  return pair<StridedImageIterator<PixelType>, Accessor>
3257  (ul, a);
3258 }
3259 
3260 template <class PixelType, class Accessor>
3261 inline pair<StridedImageIterator<PixelType>, Accessor>
3262 maskImage(MultiArrayView<2, PixelType, StridedArrayTag> & img, Accessor a)
3263 {
3264  StridedImageIterator<PixelType>
3265  ul(img.data(), 1, img.stride(0), img.stride(1));
3266  return pair<StridedImageIterator<PixelType>, Accessor>
3267  (ul, a);
3268 }
3269 
3270 // -------------------------------------------------------------------
3271 
3272 template <class PixelType>
3273 inline triple<ConstStridedImageIterator<PixelType>,
3274  ConstStridedImageIterator<PixelType>,
3276 srcImageRange(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
3277 {
3278  ConstStridedImageIterator<PixelType>
3279  ul(img.data(), 1, img.stride(0), img.stride(1));
3280  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3281  return triple<ConstStridedImageIterator<PixelType>,
3282  ConstStridedImageIterator<PixelType>,
3283  Accessor>
3284  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3285 }
3286 
3287 template <class PixelType>
3288 inline triple<ConstImageIterator<PixelType>,
3291 srcImageRange(MultiArrayView<2, PixelType, UnstridedArrayTag> const & img)
3292 {
3293  ConstImageIterator<PixelType>
3294  ul(img.data(), img.stride(1));
3295  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3296  return triple<ConstImageIterator<PixelType>,
3297  ConstImageIterator<PixelType>,
3298  Accessor>
3299  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3300 }
3301 
3302 template <class PixelType>
3303 inline pair< ConstStridedImageIterator<PixelType>,
3306 {
3307  ConstStridedImageIterator<PixelType>
3308  ul(img.data(), 1, img.stride(0), img.stride(1));
3309  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3310  return pair<ConstStridedImageIterator<PixelType>,
3311  Accessor>
3312  (ul, Accessor());
3313 }
3314 
3315 template <class PixelType>
3316 inline pair< ConstImageIterator<PixelType>,
3319 {
3320  ConstImageIterator<PixelType>
3321  ul(img.data(), img.stride(1));
3322  typedef typename AccessorTraits<PixelType>::default_const_accessor Accessor;
3323  return pair<ConstImageIterator<PixelType>,
3324  Accessor>
3325  (ul, Accessor());
3326 }
3327 
3328 template <class PixelType>
3329 inline triple< StridedImageIterator<PixelType>,
3330  StridedImageIterator<PixelType>,
3333 {
3334  StridedImageIterator<PixelType>
3335  ul(img.data(), 1, img.stride(0), img.stride(1));
3336  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3337  return triple<StridedImageIterator<PixelType>,
3338  StridedImageIterator<PixelType>,
3339  Accessor>
3340  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3341 }
3342 
3343 template <class PixelType>
3344 inline triple< ImageIterator<PixelType>,
3348 {
3349  ImageIterator<PixelType>
3350  ul(img.data(), img.stride(1));
3351  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3352  return triple<ImageIterator<PixelType>,
3353  ImageIterator<PixelType>,
3354  Accessor>
3355  (ul, ul + Size2D(img.shape(0), img.shape(1)), Accessor());
3356 }
3357 
3358 template <class PixelType>
3359 inline pair< StridedImageIterator<PixelType>,
3362 {
3363  StridedImageIterator<PixelType>
3364  ul(img.data(), 1, img.stride(0), img.stride(1));
3365  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3366  return pair<StridedImageIterator<PixelType>, Accessor>
3367  (ul, Accessor());
3368 }
3369 
3370 template <class PixelType>
3371 inline pair< ImageIterator<PixelType>,
3374 {
3375  ImageIterator<PixelType> ul(img.data(), img.stride(1));
3376  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3377  return pair<ImageIterator<PixelType>, Accessor>(ul, Accessor());
3378 }
3379 
3380 template <class PixelType>
3381 inline pair< ConstStridedImageIterator<PixelType>,
3383 maskImage(MultiArrayView<2, PixelType, StridedArrayTag> const & img)
3384 {
3385  ConstStridedImageIterator<PixelType>
3386  ul(img.data(), 1, img.stride(0), img.stride(1));
3387  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3388  return pair<ConstStridedImageIterator<PixelType>, Accessor>
3389  (ul, Accessor());
3390 }
3391 
3392 template <class PixelType>
3393 inline pair< ConstImageIterator<PixelType>,
3396 {
3397  ConstImageIterator<PixelType>
3398  ul(img.data(), img.stride(1));
3399  typedef typename AccessorTraits<PixelType>::default_accessor Accessor;
3400  return pair<ConstImageIterator<PixelType>, Accessor>
3401  (ul, Accessor());
3402 }
3403 
3404 /********************************************************/
3405 /* */
3406 /* makeBasicImageView */
3407 /* */
3408 /********************************************************/
3409 
3410 /** \addtogroup MultiArrayToImage Create BasicImageView from MultiArrayViews
3411 
3412  Some convenience functions for wrapping a \ref vigra::MultiArrayView's
3413  data in a \ref vigra::BasicImageView.
3414 */
3415 //@{
3416 /** Create a \ref vigra::BasicImageView from an unstrided 2-dimensional
3417  \ref vigra::MultiArrayView.
3418 
3419  The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
3420  as the original \ref vigra::MultiArrayView.
3421 */
3422 template <class T, class Stride>
3425 {
3426  vigra_precondition(array.isUnstrided(),
3427  "makeBasicImageView(array): array must be unstrided (i.e. array.isUnstrided() == true).");
3428  return BasicImageView <T> (array.data (), array.shape (0),
3429  array.shape (1), array.stride(1));
3430 }
3431 
3432 /** Create a \ref vigra::BasicImageView from a 3-dimensional
3433  \ref vigra::MultiArray.
3434 
3435  This wrapper flattens the two innermost dimensions of the array
3436  into single rows of the resulting image.
3437  The \ref vigra::BasicImageView will have the same <tt>value_type </tt>
3438  as the original \ref vigra::MultiArray.
3439 */
3440 template <class T>
3443 {
3444  vigra_precondition(array.stride(1) == array.shape(0),
3445  "makeBasicImageView(): cannot join strided dimensions");
3446  return BasicImageView <T> (array.data (),
3447  array.shape (0)*array.shape (1), array.shape (2), array.stride(2));
3448 }
3449 
3450 /** Create a \ref vigra::BasicImageView from a 3-dimensional
3451  \ref vigra::MultiArray.
3452 
3453  This wrapper only works if <tt>T</tt> is a scalar type and the
3454  array's innermost dimension has size 3. It then re-interprets
3455  the data array as a 2-dimensional array with value_type
3456  <tt>RGBValue<T></tt>.
3457 */
3458 template <class T, class Stride>
3461 {
3462  vigra_precondition(array.shape (0) == 3,
3463  "makeRGBImageView(): array.shape(0) must be 3.");
3464  vigra_precondition(array.isUnstrided(),
3465  "makeRGBImageView(array): array must be unstrided (i.e. array.isUnstrided() == true).");
3466  return BasicImageView <RGBValue<T> > (
3467  reinterpret_cast <RGBValue <T> *> (array.data ()),
3468  array.shape (1), array.shape (2));
3469 }
3470 
3471 //@}
3472 
3473 } // namespace vigra
3474 
3475 #undef VIGRA_ASSERT_INSIDE
3476 
3477 #endif // VIGRA_MULTI_ARRAY_HXX
MultiArray & operator/=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2782
MultiArrayView< N, typename vigra::detail::ResolveMultiband< T >::type, typename vigra::detail::ResolveMultiband< T >::Stride > view_type
Definition: multi_array.hxx:2432
const value_type & const_reference
Definition: multi_array.hxx:675
MultiArrayView(const difference_type &shape, const difference_type &stride, const_pointer ptr)
Definition: multi_array.hxx:808
MultiArray & operator=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2742
void sum(MultiArrayView< N, U, S > sums) const
Definition: multi_array.hxx:1787
MultiArrayView & operator=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:949
iterator end()
Definition: multi_array.hxx:1885
Sequential iterator for MultiArrayView.
Definition: multi_fwd.hxx:161
MultiArrayView & operator+=(T const &rhs)
Definition: multi_array.hxx:915
MultiArray< N, T > matrix_type
Definition: multi_array.hxx:725
MultiArray< N, T, A > matrix_type
Definition: multi_array.hxx:2442
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:2450
MultiArrayShape< actual_dimension >::type difference_type
Definition: multi_array.hxx:687
MultiArrayView & operator=(value_type const &v)
Definition: multi_array.hxx:884
MultiArray & operator+=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2752
MultiArray()
Definition: multi_array.hxx:2536
const difference_type & shape() const
Definition: multi_array.hxx:1596
ActualDimension
Definition: multi_array.hxx:663
MultiArrayView< N, T, StrideTag > view_type
Definition: multi_array.hxx:721
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:743
MultiArray(allocator_type const &alloc)
Definition: multi_array.hxx:2543
difference_type_1 width() const
Definition: multi_array.hxx:1618
MultiArray & operator=(value_type const &v)
Definition: multi_array.hxx:2639
A allocator_type
Definition: multi_array.hxx:2438
U product() const
Definition: multi_array.hxx:1804
view_type::iterator iterator
Definition: multi_array.hxx:2496
reference operator[](difference_type_1 d)
Definition: multi_array.hxx:1029
MultiArrayView & operator-=(T const &rhs)
Definition: multi_array.hxx:923
difference_type size_type
Definition: multi_array.hxx:695
MultiArrayView & operator*=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:979
pointer data() const
Definition: multi_array.hxx:1846
void deallocate(pointer &ptr, difference_type_1 s)
Definition: multi_array.hxx:3098
Definition: array_vector.hxx:954
difference_type_1 elementCount() const
Definition: multi_array.hxx:1578
FFTWComplex< R >::SquaredNormType squaredNorm(const FFTWComplex< R > &a)
squared norm (= squared magnitude)
Definition: fftw3.hxx:1044
iterator begin()
Definition: multi_array.hxx:1869
MultiArrayView & operator/=(T const &rhs)
Definition: multi_array.hxx:939
void reshape(const difference_type &shape)
Definition: multi_array.hxx:2809
view_type::traverser traverser
Definition: multi_array.hxx:2478
Initialize array by a linear sequence in scan order.
Definition: multi_fwd.hxx:105
void reset()
Definition: multi_array.hxx:838
Standard 2D random access const iterator for images that store the data as a linear array...
Definition: imageiterator.hxx:893
BasicImageView< RGBValue< T > > makeRGBImageView(MultiArrayView< 3, T, Stride > const &array)
Definition: multi_array.hxx:3460
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:797
Definition: accessor.hxx:43
const_iterator begin() const
Definition: multi_array.hxx:1877
StridedScanOrderIterator< actual_dimension, T, T &, T * > iterator
Definition: multi_array.hxx:703
vigra::detail::MultiIteratorChooser< StrideTag >::template Traverser< actual_dimension, T, T const &, T const * >::type const_traverser
Definition: multi_array.hxx:717
MultiArrayView & operator/=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:989
NormTraits< MultiArrayView >::NormType norm(int type=2, bool useSquaredNorm=true) const
Definition: multi_array.hxx:2320
MultiArrayView< N, T, StridedArrayTag > transpose() const
Definition: multi_array.hxx:1515
view_type::difference_type difference_type
Definition: multi_array.hxx:2470
void meanVariance(U *mean, U *variance) const
Definition: multi_array.hxx:1728
FFTWComplex< R > & operator-=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
subtract-assignment
Definition: fftw3.hxx:867
MultiArray(multi_math::MultiMathOperand< Expression > const &rhs, allocator_type const &alloc=allocator_type())
Definition: multi_array.hxx:2597
Two dimensional size object.
Definition: diff2d.hxx:482
view_type::const_traverser const_traverser
Definition: multi_array.hxx:2482
Const iterator to be used when pixels are to be skipped.
Definition: imageiterator.hxx:1026
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:712
difference_type_1 size() const
Definition: multi_array.hxx:1589
FFTWComplex< R > & operator+=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
add-assignment
Definition: fftw3.hxx:859
void swapData(MultiArrayView< N, T2, C2 > rhs)
Definition: multi_array.hxx:1223
NormTraits< MultiArrayView >::SquaredNormType squaredNorm() const
Definition: multi_array.hxx:1817
Definition: multi_fwd.hxx:63
bool operator==(MultiArrayView< N, U, C1 > const &rhs) const
Definition: multi_array.hxx:1647
view_type::reference reference
Definition: multi_array.hxx:2458
NumericTraits< V >::Promote prod(TinyVectorBase< V, SIZE, D1, D2 > const &l)
product of the vector&#39;s elements
Definition: tinyvector.hxx:2097
BasicImageView< T > makeBasicImageView(MultiArrayView< 2, T, Stride > const &array)
Definition: multi_array.hxx:3424
MultiArrayIndex difference_type_1
Definition: multi_array.hxx:699
MultiArrayView< N, Multiband< value_type >, StrideTag > multiband() const
Definition: multi_array.hxx:1431
const difference_type & stride() const
Definition: multi_array.hxx:1632
bool any() const
Definition: multi_array.hxx:1698
bool operator!=(MultiArrayView< N, U, C1 > const &rhs) const
Definition: multi_array.hxx:1658
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector&#39;s elements
Definition: tinyvector.hxx:2073
MultiArray & operator*=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2772
value_type & reference
Definition: multi_array.hxx:671
MultiArrayView & operator-=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:969
const_reference operator[](difference_type_1 d) const
Definition: multi_array.hxx:1045
difference_type_1 stride(int n) const
Definition: multi_array.hxx:1639
bool isInside(difference_type const &p) const
Definition: multi_array.hxx:1665
difference_type_1 coordinateToScanOrderIndex(const difference_type &d) const
Definition: multi_array.hxx:1062
bool operator==(FFTWComplex< R > const &a, const FFTWComplex< R > &b)
equal
Definition: fftw3.hxx:825
const_iterator end() const
Definition: multi_array.hxx:1893
MultiArray & init(const U &init)
Definition: multi_array.hxx:2799
MultiArrayView< 1, T, StridedArrayTag > diagonal() const
Definition: multi_array.hxx:1452
allocator_type m_alloc
Definition: multi_array.hxx:2508
void minmax(T *minimum, T *maximum) const
Definition: multi_array.hxx:1712
MultiArrayView(const MultiArrayView< N, T, Stride > &other)
Definition: multi_array.hxx:786
void copy(const MultiArrayView< N, U, CN > &rhs)
Definition: multi_array.hxx:1174
BasicImage using foreign memory.
Definition: basicimageview.hxx:74
void copy(const MultiArrayView &rhs)
Definition: multi_array.hxx:1164
difference_type scanOrderIndexToCoordinate(difference_type_1 d) const
Definition: multi_array.hxx:1053
Definition: metaprogramming.hxx:105
allocator_type const & allocator() const
Definition: multi_array.hxx:2858
MultiArrayView< N, typename ExpandElementResult< T >::type, StridedArrayTag > bindElementChannel(difference_type_1 i) const
Definition: multi_array.hxx:1363
view_type::size_type size_type
Definition: multi_array.hxx:2466
FFTWComplex< R > & operator*=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
multiply-assignment
Definition: fftw3.hxx:875
difference_type_1 size(difference_type_1 n) const
Definition: multi_array.hxx:1603
view_type::const_pointer const_pointer
Definition: multi_array.hxx:2454
view_type::value_type value_type
Definition: multi_array.hxx:2446
Definition: metaprogramming.hxx:112
const_traverser traverser_begin() const
Definition: multi_array.hxx:1910
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:667
MultiArrayShape< 2 >::type Shape2
shape type for MultiArray<2, T>
Definition: multi_shape.hxx:254
MultiArrayView< N, T, StridedArrayTag > transpose(const difference_type &permutation) const
Definition: multi_array.hxx:1541
Fundamental class template for images.
Definition: basicimage.hxx:473
bool hasData() const
Definition: multi_array.hxx:1861
pointer m_ptr
Definition: multi_array.hxx:752
~MultiArray()
Definition: multi_array.hxx:2790
difference_type_1 height() const
Definition: multi_array.hxx:1625
view_type::difference_type_1 difference_type_1
Definition: multi_array.hxx:2474
MultiArrayView & operator+=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:959
MultiArrayShape< 1 >::type Shape1
shape type for MultiArray<1, T>
Definition: multi_shape.hxx:253
MultiArrayView & operator=(MultiArrayView< N, U, C1 > const &rhs)
Definition: multi_array.hxx:874
Standard 2D random access iterator for images that store the data in a linear array.
Definition: imageiterator.hxx:848
MultiArray(const MultiArray &rhs)
Definition: multi_array.hxx:2587
Encapsulate read access to the values an iterator points to.
Definition: accessor.hxx:269
MultiArrayView(BasicImage< T, ALLOC > const &image)
Definition: multi_array.hxx:822
bool isUnstrided(unsigned int dimension=N-1) const
Definition: multi_array.hxx:1234
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:652
void transformMultiArray(...)
Transform a multi-dimensional array with a unary function or functor.
MultiArrayView & init(const U &init)
Definition: multi_array.hxx:1154
MultiArray & operator-=(multi_math::MultiMathOperand< Expression > const &rhs)
Definition: multi_array.hxx:2762
void swap(MultiArrayView &other)
Definition: multi_array.hxx:1199
void swapData(MultiArrayView rhs)
Definition: multi_array.hxx:1212
value_type * pointer
Definition: multi_array.hxx:679
FFTWComplex< R > & operator/=(FFTWComplex< R > &a, const FFTWComplex< R > &b)
divide-assignment
Definition: fftw3.hxx:884
traverser traverser_end()
Definition: multi_array.hxx:1920
MultiArrayView subarray(difference_type p, difference_type q) const
Definition: multi_array.hxx:1476
Iterator to be used when pixels are to be skipped.
Definition: imageiterator.hxx:966
Class for a single RGB value.
Definition: accessor.hxx:938
bool all() const
Definition: multi_array.hxx:1685
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:133
StridedScanOrderIterator< actual_dimension, T, T const &, T const * > const_iterator
Definition: multi_array.hxx:707
bool isOutside(difference_type const &p) const
Definition: multi_array.hxx:1674
view_type::const_iterator const_iterator
Definition: multi_array.hxx:2500
MultiArrayView & operator=(MultiArrayView const &rhs)
Definition: multi_array.hxx:855
MultiArrayView & operator*=(T const &rhs)
Definition: multi_array.hxx:931
difference_type m_stride
Definition: multi_array.hxx:748
void init(Iterator i, Iterator end)
Definition: tinyvector.hxx:708
U sum() const
Definition: multi_array.hxx:1751
const value_type * const_pointer
Definition: multi_array.hxx:683
difference_type_1 shape(difference_type_1 n) const
Definition: multi_array.hxx:1611
traverser traverser_begin()
Definition: multi_array.hxx:1901
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:1491
MultiArrayView()
Definition: multi_array.hxx:777
difference_type key_type
Definition: multi_array.hxx:691
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:2462
void allocate(pointer &ptr, difference_type_1 s, const_reference init)
Definition: multi_array.hxx:3027
const_traverser traverser_end() const
Definition: multi_array.hxx:1931
difference_type strideOrdering() const
Definition: multi_array.hxx:1565

© 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