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

multi_array.hxx |

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

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