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

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

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