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

© 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.10.0