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

multi_array.hxx |

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.11.0