vigra - vigra/multi_array.hxx Source File

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

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