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

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