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