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

multi_iterator.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2003-2012 by Gunnar Kedenburg and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* ( Version 1.3.0, Sep 10 2004 ) */
7 /* The VIGRA Website is */
8 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
9 /* Please direct questions, bug reports, and contributions to */
10 /* ullrich.koethe@iwr.uni-heidelberg.de or */
11 /* vigra@informatik.uni-hamburg.de */
12 /* */
13 /* Permission is hereby granted, free of charge, to any person */
14 /* obtaining a copy of this software and associated documentation */
15 /* files (the "Software"), to deal in the Software without */
16 /* restriction, including without limitation the rights to use, */
17 /* copy, modify, merge, publish, distribute, sublicense, and/or */
18 /* sell copies of the Software, and to permit persons to whom the */
19 /* Software is furnished to do so, subject to the following */
20 /* conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be */
23 /* included in all copies or substantial portions of the */
24 /* Software. */
25 /* */
26 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
27 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
28 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
29 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
30 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
31 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
32 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
33 /* OTHER DEALINGS IN THE SOFTWARE. */
34 /* */
35 /************************************************************************/
36
37 #ifndef VIGRA_MULTI_ITERATOR_HXX
38 #define VIGRA_MULTI_ITERATOR_HXX
39
40 #include <sys/types.h>
41 #include "iteratortags.hxx"
42 #include "multi_iterator_coupled.hxx"
43
44 namespace vigra {
45
46 template<unsigned int N, class DirectedTag>
47 class GridGraph;
48
49 /** \addtogroup MultiIteratorGroup
50 */
51 //@{
52
53 /** \brief Iterate over a virtual array where each element contains its coordinate.
54
55 MultiCoordinateIterator behaves like a read-only random access iterator.
56 It moves accross the given region of interest in scan-order (with the first
57 index changing most rapidly), and dereferencing the iterator returns the
58 coordinate (i.e. multi-dimensional index) of the current array element.
59 The functionality is thus similar to a meshgrid in Matlab or numpy.
60
61 Internally, it is just a wrapper of a \ref CoupledScanOrderIterator that
62 has been created without any array and whose reference type is not a
63 \ref CoupledHandle, but the coordinate itself.
64
65 The iterator supports all functions listed in the STL documentation for
66 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
67
68 <b>Usage:</b>
69
70 <b>\#include</b> <vigra/multi_iterator.hxx><br/>
71 Namespace: vigra
72
73 \code
74 MultiCoordinateIterator<3> i(Shape3(3,2,1)), end = i.getEndIterator();
75
76 for(; i != end; ++i)
77 std::cout << *i << "\n";
78
79 // Output:
80 // (0, 0, 0)
81 // (1, 0, 0)
82 // (2, 0, 0)
83 // (0, 1, 0)
84 // (1, 1, 0)
85 // (2, 1, 0)
86 \endcode
87 */
88 template<unsigned int N>
89 class MultiCoordinateIterator
90 : public CoupledScanOrderIterator<N>
91 {
92 public:
93 typedef CoupledScanOrderIterator<N> base_type;
94
95 typedef typename base_type::shape_type shape_type;
96 typedef typename base_type::difference_type difference_type;
97 typedef MultiCoordinateIterator iterator;
98 typedef std::random_access_iterator_tag iterator_category;
99
100 typedef typename base_type::value_type handle_type;
101 typedef typename handle_type::value_type value_type;
102 typedef typename handle_type::reference reference;
103 typedef typename handle_type::const_reference const_reference;
104 typedef typename handle_type::pointer pointer;
105 typedef typename handle_type::const_pointer const_pointer;
106
107 MultiCoordinateIterator()
108 : base_type(handle_type())
109 {}
110
111 explicit MultiCoordinateIterator(shape_type const & shape)
112 : base_type(handle_type(shape))
113 {}
114
115 explicit MultiCoordinateIterator(shape_type const & start, shape_type const & end)
116 : base_type(handle_type(end))
117 {
118 this->restrictToSubarray(start, end);
119 }
120
121 template<class DirectedTag>
122 explicit MultiCoordinateIterator(GridGraph<N, DirectedTag> const & g)
123 : base_type(handle_type(g.shape()))
124 {}
125
126 // dereferencing the iterator yields the coordinate object
127 // (used as vertex_descriptor)
128 reference operator*()
129 {
130 return this->template get<0>();
131 }
132
133 const_reference operator*() const
134 {
135 return this->template get<0>();
136 }
137
138 operator value_type() const
139 {
140 return *(*this);
141 }
142
143 pointer operator->()
144 {
145 return &this->template get<0>();
146 }
147
148 const_pointer operator->() const
149 {
150 return &this->template get<0>();
151 }
152
153 value_type operator[](MultiArrayIndex i) const
154 {
155 return *(MultiCoordinateIterator(*this) += i);
156 }
157
158 MultiCoordinateIterator & operator++()
159 {
160 base_type::operator++();
161 return *this;
162 }
163
164 MultiCoordinateIterator operator++(int)
165 {
166 MultiCoordinateIterator res(*this);
167 ++*this;
168 return res;
169 }
170
171 MultiCoordinateIterator & operator+=(MultiArrayIndex i)
172 {
173 base_type::operator+=(i);
174 return *this;
175 }
176
177 MultiCoordinateIterator & operator+=(const shape_type &coordOffset)
178 {
179 base_type::operator+=(coordOffset);
180 return *this;
181 }
182
183 MultiCoordinateIterator & operator--()
184 {
185 base_type::operator--();
186 return *this;
187 }
188
189 MultiCoordinateIterator operator--(int)
190 {
191 MultiCoordinateIterator res(*this);
192 --*this;
193 return res;
194 }
195
196 MultiCoordinateIterator & operator-=(MultiArrayIndex i)
197 {
198 return operator+=(-i);
199 }
200
201 MultiCoordinateIterator & operator-=(const shape_type &coordOffset)
202 {
203 return operator+=(-coordOffset);
204 }
205
206 MultiCoordinateIterator getEndIterator() const
207 {
208 return MultiCoordinateIterator(base_type::getEndIterator());
209 }
210
211 MultiCoordinateIterator operator+(MultiArrayIndex d) const
212 {
213 return MultiCoordinateIterator(*this) += d;
214 }
215
216 MultiCoordinateIterator operator-(MultiArrayIndex d) const
217 {
218 return MultiCoordinateIterator(*this) -= d;
219 }
220
221 MultiCoordinateIterator operator+(const shape_type &coordOffset) const
222 {
223 return MultiCoordinateIterator(*this) += coordOffset;
224 }
225
226 MultiCoordinateIterator operator-(const shape_type &coordOffset) const
227 {
228 return MultiCoordinateIterator(*this) -= coordOffset;
229 }
230
231 MultiArrayIndex operator-(const MultiCoordinateIterator & other) const
232 {
233 return base_type::operator-(other);
234 }
235
236 protected:
237 MultiCoordinateIterator(base_type const & base)
238 : base_type(base)
239 {}
240 };
241
242 /** \brief Sequential iterator for MultiArrayView.
243
244 This iterator provides STL-compatible random access iterator functionality for arbitrary
245 \ref MultiArrayView instances, regardless of their shapes and strides. The
246 class uses an implementation that minimizes speed penalties that could result from
247 non-trivial strides. The <i>scan-order</i> is defined such that dimensions are iterated
248 from front to back (first to last).
249
250 You normally construct instances of this class by calling \ref MultiArrayView::begin()
251 and \ref MultiArrayView::end().
252
253 The iterator supports all functions listed in the STL documentation for
254 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
255
256 <b>\#include</b> <vigra/multi_iterator.hxx><br/>
257 Namespace: vigra
258 */
259 template <unsigned int N, class T, class REFERENCE, class POINTER>
260 class StridedScanOrderIterator
261 : public CoupledIteratorType<N, T>::type
262 {
263 public:
264 typedef typename CoupledIteratorType<N, T>::type base_type;
265
266 typedef typename base_type::shape_type shape_type;
267 typedef typename base_type::difference_type difference_type;
268 typedef StridedScanOrderIterator iterator;
269 typedef std::random_access_iterator_tag iterator_category;
270
271 typedef T value_type;
272 typedef REFERENCE reference;
273 typedef T const & const_reference;
274 typedef POINTER pointer;
275 typedef T const * const_pointer;
276
277 StridedScanOrderIterator()
278 : base_type()
279 {}
280
281 template <class S>
282 explicit StridedScanOrderIterator(MultiArrayView<N, T, S> const & view)
283 : base_type(createCoupledIterator(view))
284 {}
285
286 StridedScanOrderIterator(POINTER p, shape_type const & shape, shape_type const & strides)
287 : base_type(createCoupledIterator(MultiArrayView<N, T, StridedArrayTag>(shape, strides, const_cast<T *>(p))))
288 {}
289
290 reference operator*()
291 {
292 return this->template get<1>();
293 }
294
295 const_reference operator*() const
296 {
297 return this->template get<1>();
298 }
299
300 pointer operator->()
301 {
302 return &this->template get<1>();
303 }
304
305 const_pointer operator->() const
306 {
307 return &this->template get<1>();
308 }
309
310 reference operator[](MultiArrayIndex i)
311 {
312 return *(StridedScanOrderIterator(*this) += i);
313 }
314
315 const_reference operator[](MultiArrayIndex i) const
316 {
317 return *(StridedScanOrderIterator(*this) += i);
318 }
319
320 StridedScanOrderIterator & operator++()
321 {
322 base_type::operator++();
323 return *this;
324 }
325
326 StridedScanOrderIterator operator++(int)
327 {
328 StridedScanOrderIterator res(*this);
329 ++*this;
330 return res;
331 }
332
333 StridedScanOrderIterator & operator+=(MultiArrayIndex i)
334 {
335 base_type::operator+=(i);
336 return *this;
337 }
338
339 StridedScanOrderIterator & operator+=(const shape_type &coordOffset)
340 {
341 base_type::operator+=(coordOffset);
342 return *this;
343 }
344
345 StridedScanOrderIterator & operator--()
346 {
347 base_type::operator--();
348 return *this;
349 }
350
351 StridedScanOrderIterator operator--(int)
352 {
353 StridedScanOrderIterator res(*this);
354 --*this;
355 return res;
356 }
357
358 StridedScanOrderIterator & operator-=(MultiArrayIndex i)
359 {
360 return operator+=(-i);
361 }
362
363 StridedScanOrderIterator & operator-=(const shape_type &coordOffset)
364 {
365 return operator+=(-coordOffset);
366 }
367
368 StridedScanOrderIterator getEndIterator() const
369 {
370 return StridedScanOrderIterator(base_type::getEndIterator());
371 }
372
373 StridedScanOrderIterator operator+(MultiArrayIndex d) const
374 {
375 return StridedScanOrderIterator(*this) += d;
376 }
377
378 StridedScanOrderIterator operator-(MultiArrayIndex d) const
379 {
380 return StridedScanOrderIterator(*this) -= d;
381 }
382
383 MultiArrayIndex operator-(StridedScanOrderIterator const & other) const
384 {
385 return base_type::operator-(other);
386 }
387
388 StridedScanOrderIterator operator+(const shape_type &coordOffset) const
389 {
390 return StridedScanOrderIterator(*this) += coordOffset;
391 }
392
393 StridedScanOrderIterator operator-(const shape_type &coordOffset) const
394 {
395 return StridedScanOrderIterator(*this) -= coordOffset;
396 }
397
398 MultiArrayIndex index() const
399 {
400 return this->scanOrderIndex();
401 }
402
403 protected:
404 StridedScanOrderIterator(base_type const & base)
405 : base_type(base)
406 {}
407 };
408
409 //@}
410
411 /** \page MultiIteratorPage Multi-dimensional Array Iterators
412
413 General iterators for arrays of arbitrary dimension.
414
415 <p>
416 <UL style="list-style-image:url(documents/bullet.gif)">
417 <LI> \ref vigra::MultiArrayShape
418 <BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayView or \ref vigra::MultiIterator</em>
419 <LI> \ref vigra::MultiIterator
420 <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArrayView</em>
421 <LI> \ref vigra::StridedMultiIterator
422 <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayView</em>
423 <LI> \ref vigra::StridedScanOrderIterator
424 <BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \ref vigra::MultiArrayView</em>
425 <LI> \ref vigra::CoupledScanOrderIterator
426 <BR>&nbsp;&nbsp;&nbsp;<em>Iterate over multiple images simultaneously in scan order</em>
427 </UL>
428 </p>
429
430 <p>
431 The Multidimensional Iterator concept allows navigation on arrays
432 of arbitrary dimension. It provides two modes of iteration:
433 <em>direct traversal</em>, and <em>hierarchical traversal</em>.
434 In general, hierarchical traversal will be faster, while only
435 direct traversal allows for true random access in all dimensions.
436 Via the <tt>dim<K>()</tt> function, operations applying to a particular
437 dimension can be used in the direct traversal mode. In contrast,
438 direct traversal functions should not be used in the hierarchical mode
439 because the hierarchical functions are only well-defined if the
440 iterator points to element 0 in all dimensions below its current dimension.
441 The current dimension of a <tt>MultiIterator<N, ...></tt> is <tt>N-1</tt>.
442 </p>
443 <h3>General Requirements for MultiIterator</h3>
444 <p>
445 <table border=2 cellspacing=0 cellpadding=2 width="100%">
446 <tr><th colspan=2>
447 Local Types
448 </th><th>
449 Meaning
450 </th>
451 </tr>
452 <tr><td colspan=2>
453 <tt>MultiIterator::value_type</tt></td><td>the underlying arrays's pixel type</td>
454 </tr>
455 <tr><td colspan=2>
456 <tt>MultiIterator::reference</tt></td>
457 <td>the iterator's reference type (return type of <TT>*iter</TT>). Will be
458 <tt>value_type &</tt> for a mutable iterator, and convertible to
459 <tt>value_type const &</tt> for a const iterator.</td>
460 </tr>
461 <tr><td colspan=2>
462 <tt>MultiIterator::pointer</tt></td>
463 <td>the iterator's pointer type (return type of <TT>iter.operator->()</TT>). Will be
464 <tt>value_type *</tt> for a mutable iterator, and convertible to
465 <tt>value_type const *</tt> for a const iterator.</td>
466 </tr>
467 <tr><td colspan=2>
468 <tt>MultiIterator::iterator_category</tt></td>
469 <td>the iterator tag (<tt>vigra::multi_dimensional_traverser_tag</tt>)</td>
470 </tr>
471 <tr><th>
472 Operation
473 </th><th>
474 Result
475 </th><th>
476 Semantics
477 </th>
478 </tr>
479 <tr><td colspan=2>
480 <tt>MultiIterator k;</tt></td><td>default constructor</td>
481 </tr>
482 <tr><td colspan=2>
483 <tt>MultiIterator k(i);</tt></td><td>copy constructor</td>
484 </tr>
485 <tr>
486 <td><tt>k = i</tt></td>
487 <td><tt>MultiIterator &</tt></td><td>assignment</td>
488 </tr>
489 <tr>
490 <td><tt>i == j</tt></td><td><tt>bool</tt></td>
491 <td>equality (iterators point to the same element)</td>
492 </tr>
493 <tr>
494 <td><tt>i != j</tt></td><td><tt>bool</tt></td>
495 <td>inequality (iterators don't point to the same element)</td>
496 </tr>
497 <tr>
498 <td><tt>*i</tt></td><td><tt>MultiIterator::reference</tt></td>
499 <td>access the current element</td>
500 </tr>
501 <tr>
502 <td><tt>i->member()</tt></td><td>depends on operation</td>
503 <td>call member function of underlying pixel type via <tt>operator-></tt> of iterator</td>
504 </tr>
505 </table>
506 </p>
507 <h3>Requirements for Direct Traversal</h3>
508 <p>
509 <table border=2 cellspacing=0 cellpadding=2 width="100%">
510 <tr><th colspan=2>
511 Local Types
512 </th><th>
513 Meaning
514 </th>
515 </tr>
516 <tr><td colspan=2>
517 <tt>MultiIterator::multi_difference_type</tt></td>
518 <td>the iterator's multi-dimensional difference type (<TT>TinyVector<MultiArrayIndex, N></TT>)</td>
519 </tr>
520 <tr><th>
521 Operation
522 </th><th>
523 Result
524 </th><th>
525 Semantics
526 </th>
527 </tr>
528 <tr>
529 <td><tt>i += diff</tt></td><td><tt>MultiIterator &</tt></td>
530 <td>add offset to current position</td>
531 </tr>
532 <tr>
533 <td><tt>i -= diff</tt></td><td><tt>MultiIterator &</tt></td>
534 <td>subtract offset from current position</td>
535 </tr>
536 <tr>
537 <td><tt>i + diff</tt></td><td><tt>MultiIterator</tt></td>
538 <td>create traverser by adding offset</td>
539 </tr>
540 <tr>
541 <td><tt>i - diff</tt></td><td><tt>MultiIterator</tt></td>
542 <td>create traverser by subtracting offset</td>
543 </tr>
544 <tr>
545 <td><tt>i[diff]</tt></td><td><tt>MultiIterator::reference</tt></td>
546 <td>access element at offset <tt>diff</tt></td>
547 </tr>
548 <tr>
549 <td><tt>i.dim<K>()</tt></td><td><tt>MultiIterator<K+1, T, ...></tt></td>
550 <td>Access the traverser with the current dimension set to K. Typically used to call
551 navigation functions referring to a particular dimension.<br>
552 Example (assuming <tt>i, j</tt> are 3-dimensional):<br>
553 \code
554 i.dim<0>()++; // increment dimension 0
555 i.dim<1>()++; // increment dimension 1
556 i.dim<2>()++; // increment dimension 2
557
558 j += MultiIterator::multi_difference_type(1,1,1); // same effect
559 \endcode
560 </td>
561 </tr>
562 <tr><td colspan=3>
563 <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
564 <tt>diff</tt> is of type <tt>MultiIterator::multi_difference_type</tt><br>
565 <tt>K</tt> is an integer compile-time constant
566 </td>
567 </tr>
568 </table>
569 </p>
570 <p>
571 Note that it is impossible to support an <tt>operator-</tt> between two iterators which returns
572 a <tt>MultiIterator::multi_difference_type</tt> because it is impossible to decide to which
573 dimension a difference applies. Consider for example, a 2-dimensional iterator <tt>i</tt>, and
574 let <tt>j = i + multi_difference_type(width, 0)</tt>, <tt>k = i + multi_difference_type(0,1)</tt>,
575 where <tt>width</tt> is the array's total width. In general, <tt>j</tt> and <tt>k</tt> point to
576 the same memory location, so that the two cases cannot easily be distinguished (it is possible,
577 but iterator performance will suffer significantly, as is experienced with
578 \ref vigra::ImageIterator where differencing is allowed).
579 </p>
580
581 <h3>Requirements for Hierarchical Traversal</h3>
582 <p>
583 <table border=2 cellspacing=0 cellpadding=2 width="100%">
584 <tr><th colspan=2>
585 Local Types
586 </th><th>
587 Meaning
588 </th>
589 </tr>
590 <tr><td colspan=2>
591 <tt>MultiIterator::difference_type</tt></td>
592 <td>the iterator's difference type (<TT>MultiArrayIndex</TT>)</td>
593 </tr>
594 <tr><td colspan=2>
595 <tt>MultiIterator::next_type</tt></td><td>type of the next iterator
596 (referring to the next lower dimension) in the hierarchy</td>
597 </tr>
598 <tr><th>
599 Operation
600 </th><th>
601 Result
602 </th><th>
603 Semantics
604 </th>
605 </tr>
606 <tr>
607 <td><tt>++i</tt></td><td><tt>MultiIterator &</tt></td>
608 <td>pre-increment iterator in its current dimension</td>
609 </tr>
610 <tr>
611 <td><tt>i++</tt></td><td><tt>MultiIterator</tt></td>
612 <td>post-increment iterator in its current dimension</td>
613 </tr>
614 <tr>
615 <td><tt>--i</tt></td><td><tt>MultiIterator &</tt></td>
616 <td>pre-decrement iterator in its current dimension</td>
617 </tr>
618 <tr>
619 <td><tt>i--</tt></td><td><tt>MultiIterator</tt></td>
620 <td>post-decrement iterator in its current dimension</td>
621 </tr>
622 <tr>
623 <td><tt>i += d</tt></td><td><tt>MultiIterator &</tt></td>
624 <td>add <tt>d</tt> in current dimension</td>
625 </tr>
626 <tr>
627 <td><tt>i -= d</tt></td><td><tt>MultiIterator &</tt></td>
628 <td>subtract <tt>d</tt> in from dimension</td>
629 </tr>
630 <tr>
631 <td><tt>i + d</tt></td><td><tt>MultiIterator</tt></td>
632 <td>create new iterator by adding <tt>d</tt> in current dimension</td>
633 </tr>
634 <tr>
635 <td><tt>i - d</tt></td><td><tt>MultiIterator</tt></td>
636 <td>create new iterator by subtracting <tt>d</tt> in current dimension</td>
637 </tr>
638 <tr>
639 <td><tt>i - j</tt></td><td><tt>difference_type</tt></td>
640 <td>difference of <tt>i</tt> and <tt>j</tt> in the current dimension<br>
641 <em>Note:</em> The result of this operation is undefined if the iterator
642 doesn't point to element 0 in all dimensions below its current dimension.</td>
643 </tr>
644 <tr>
645 <td><tt>i < j</tt></td><td><tt>bool</tt></td>
646 <td><tt>i - j < 0</tt><br>
647 <em>Note:</em> The result of this operation is undefined if the iterator
648 doesn't point to element 0 in all dimensions below its current dimension.</td>
649 </tr>
650 <tr>
651 <td><tt>i[d]</tt></td><td><tt>MultiIterator::reference</tt></td>
652 <td>access element by adding offset <tt>d</tt> in current dimension</td>
653 </tr>
654 <tr>
655 <td><tt>i.begin()</tt></td><td><tt>next_type</tt></td>
656 <td>create the hierarchical iterator pointing to the first element in the
657 next lower dimension.<br>
658 <em>Note:</em> The result of this operation is undefined if the iterator
659 doesn't point to element 0 in all dimensions below its current dimension.<br>
660 Usage:<br>
661 \code
662 MultiIterator<3, int> i3 = ..., end3 = ...;
663 for(; i3 != end3; ++i3)
664 {
665 MultiIterator<3, int>::next_type i2 = i3.begin(), end2 = i3.end();
666 for(; i2 != end2; ++i2)
667 {
668 MultiIterator<3, int>::next_type::next_type i1 = i2.begin(), end1 = i2.end();
669 for(; i1 != end1; ++i1)
670 {
671 ... // do something with the current element
672 }
673 }
674 }
675
676 \endcode
677 </td>
678 </tr>
679 <tr>
680 <td><tt>i.end()</tt></td><td><tt>next_type</tt></td>
681 <td>create the hierarchical iterator pointing to the past-the-end location in the
682 next lower dimension.<br>
683 <em>Note:</em> The result of this operation is undefined if the iterator
684 doesn't point to element 0 in all dimensions below its current dimension.</td>
685 </tr>
686 <tr><td colspan=3>
687 <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
688 <tt>d</tt> is of type <tt>MultiIterator::difference_type</tt>
689 </td>
690 </tr>
691 </table>
692 </p>
693
694 */
695
696 /** \addtogroup MultiIteratorGroup
697 */
698 //@{
699
700 template <class POINTER>
701 struct MultiIteratorStrideTraits
702 {
703 typedef MultiArrayIndex stride_type;
704 typedef const stride_type* stride_array_type;
705 typedef stride_array_type shape_array_type;
706 static stride_array_type shift(stride_array_type s, unsigned d)
707 {
708 return s + d;
709 }
710 };
711
712 template <unsigned int N, class T, class REFERENCE = T &, class POINTER = T *>
713 class MultiIterator;
714
715 template <unsigned int N, class T, class REFERENCE = T &, class POINTER = T *>
716 class StridedMultiIterator;
717
718 /********************************************************/
719 /* */
720 /* MultiIterator */
721 /* */
722 /********************************************************/
723
724 /********************************************************/
725 /* */
726 /* MultiIterator<1> */
727 /* */
728 /********************************************************/
729
730 //
731 template <class T, class REFERENCE, class POINTER>
732 class MultiIterator<1, T, REFERENCE, POINTER>
733 {
734 public:
735 enum { level = 0 };
736 typedef T value_type;
737 typedef REFERENCE reference;
738 typedef const value_type &const_reference;
739 typedef POINTER pointer;
740 typedef const value_type *const_pointer;
741 typedef typename MultiArrayShape<1>::type multi_difference_type;
742 typedef MultiIteratorStrideTraits<POINTER> stride_traits;
743 typedef typename stride_traits::stride_type difference_type;
744 typedef typename stride_traits::stride_array_type difference_array_type;
745 typedef typename stride_traits::shape_array_type shape_array_type;
746 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
747 typedef std::random_access_iterator_tag iterator_category;
748
749 protected:
750 pointer m_ptr;
751
752 public:
753 MultiIterator ()
754 : m_ptr (0)
755 {}
756
757 MultiIterator (pointer ptr,
758 const difference_array_type &,
759 const shape_array_type &)
760 : m_ptr (ptr)
761 {}
762
763 void operator++ ()
764 {
765 ++m_ptr;
766 }
767
768 void operator-- ()
769 {
770 --m_ptr;
771 }
772
773 MultiIterator operator++ (int)
774 {
775 MultiIterator ret = *this;
776 ++(*this);
777 return ret;
778 }
779
780 MultiIterator operator-- (int)
781 {
782 MultiIterator ret = *this;
783 --(*this);
784 return ret;
785 }
786
787 MultiIterator &operator+= (difference_type n)
788 {
789 m_ptr += n;
790 return *this;
791 }
792
793 MultiIterator & operator+= (multi_difference_type const & d)
794 {
795 m_ptr += d[level];
796 return *this;
797 }
798
799 MultiIterator &operator-= (difference_type n)
800 {
801 m_ptr -= n;
802 return *this;
803 }
804
805 MultiIterator & operator-= (multi_difference_type const & d)
806 {
807 m_ptr -= d[level];
808 return *this;
809 }
810
811 MultiIterator operator+ (difference_type n) const
812 {
813 MultiIterator ret = *this;
814 ret += n;
815 return ret;
816 }
817
818 MultiIterator operator+ (multi_difference_type const & d) const
819 {
820 MultiIterator ret = *this;
821 ret += d;
822 return ret;
823 }
824
825 difference_type operator- (MultiIterator const & d) const
826 {
827 return (m_ptr - d.m_ptr);
828 }
829
830 MultiIterator operator- (difference_type n) const
831 {
832 MultiIterator ret = *this;
833 ret -= n;
834 return ret;
835 }
836
837 MultiIterator operator- (multi_difference_type const & d) const
838 {
839 MultiIterator ret = *this;
840 ret -= d;
841 return ret;
842 }
843
844 reference operator[] (difference_type n) const
845 {
846 return m_ptr [n];
847 }
848
849 reference operator[] (multi_difference_type const & d) const
850 {
851 return m_ptr [d[level]];
852 }
853
854 reference operator* () const
855 {
856 return *m_ptr;
857 }
858
859 pointer get () const
860 {
861 return m_ptr;
862 }
863
864 pointer operator->() const
865 {
866 return &(operator*());
867 }
868
869 bool operator!= (const MultiIterator &rhs) const
870 {
871 return m_ptr != rhs.m_ptr;
872 }
873
874 bool operator== (const MultiIterator &rhs) const
875 {
876 return m_ptr == rhs.m_ptr;
877 }
878
879 bool operator< (const MultiIterator &rhs) const
880 {
881 return m_ptr < rhs.m_ptr;
882 }
883
884 bool operator<= (const MultiIterator &rhs) const
885 {
886 return m_ptr <= rhs.m_ptr;
887 }
888
889 bool operator> (const MultiIterator &rhs) const
890 {
891 return m_ptr > rhs.m_ptr;
892 }
893
894 bool operator>= (const MultiIterator &rhs) const
895 {
896 return m_ptr >= rhs.m_ptr;
897 }
898
899 iterator iteratorForDimension(unsigned int d) const
900 {
901 vigra_precondition(d == 0,
902 "MultiIterator<1>::iteratorForDimension(d): d == 0 required");
903 const difference_type stride = 1;
904 return iterator(m_ptr, &stride, 0);
905 }
906
907 template <unsigned int K>
908 MultiIterator<K+1, T, REFERENCE, POINTER> &
909 dim()
910 {
911 return *this;
912 }
913
914 MultiIterator<1, T, REFERENCE, POINTER> &
915 dim0() { return *this; }
916
917 protected:
918
919 difference_type
920 total_stride(typename multi_difference_type::const_iterator d) const
921 {
922 return d[level];
923 }
924 };
925
926 /********************************************************/
927 /* */
928 /* MultiIterator<2> */
929 /* */
930 /********************************************************/
931
932 //
933 template <class T, class REFERENCE, class POINTER>
934 class MultiIterator<2, T, REFERENCE, POINTER>
935 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
936 : public MultiIterator<1, T, REFERENCE, POINTER>
937 #endif
938 {
939 public:
940
941 typedef MultiIterator<1, T, REFERENCE, POINTER> base_type;
942 enum { level = 1 };
943 typedef T value_type;
944 typedef REFERENCE reference;
945 typedef const value_type &const_reference;
946 typedef POINTER pointer;
947 typedef const value_type *const_pointer;
948 typedef typename MultiArrayShape<2>::type multi_difference_type;
949 typedef MultiIteratorStrideTraits<POINTER> stride_traits;
950 typedef typename stride_traits::stride_type difference_type;
951 typedef typename stride_traits::stride_array_type difference_array_type;
952 typedef typename stride_traits::shape_array_type shape_array_type;
953 typedef base_type next_type;
954 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
955 typedef multi_dimensional_traverser_tag iterator_category;
956
957 protected:
958 difference_array_type m_stride;
959 shape_array_type m_shape;
960
961 public:
962 /* use default copy constructor and assignment operator */
963
964 MultiIterator ()
965 : base_type (),
966 m_stride (0), m_shape (0)
967 {}
968
969 MultiIterator (pointer ptr,
970 const difference_array_type & stride,
971 const shape_array_type & shape)
972 : base_type (ptr, stride, shape),
973 m_stride (stride), m_shape (shape)
974 {}
975
976 void operator++ ()
977 {
978 this->m_ptr += m_stride [level];
979 }
980
981 void operator-- ()
982 {
983 this->m_ptr -= m_stride [level];
984 }
985
986 MultiIterator operator++ (int)
987 {
988 MultiIterator ret = *this;
989 ++(*this);
990 return ret;
991 }
992
993 MultiIterator operator-- (int)
994 {
995 MultiIterator ret = *this;
996 --(*this);
997 return ret;
998 }
999
1000 MultiIterator & operator+= (difference_type n)
1001 {
1002 this->m_ptr += n * m_stride [level];
1003 return *this;
1004 }
1005
1006 MultiIterator & operator+= (multi_difference_type const & d)
1007 {
1008 this->m_ptr += total_stride(d.begin());
1009 return *this;
1010 }
1011
1012 MultiIterator &operator-= (difference_type n)
1013 {
1014 this->m_ptr -= n * m_stride [level];
1015 return *this;
1016 }
1017
1018 MultiIterator & operator-= (multi_difference_type const & d)
1019 {
1020 this->m_ptr -= total_stride(d.begin());
1021 return *this;
1022 }
1023
1024 MultiIterator operator+ (difference_type n) const
1025 {
1026 MultiIterator ret = *this;
1027 ret += n;
1028 return ret;
1029 }
1030
1031 MultiIterator operator+ (multi_difference_type const & d) const
1032 {
1033 MultiIterator ret = *this;
1034 ret += d;
1035 return ret;
1036 }
1037
1038 difference_type operator- (MultiIterator const & d) const
1039 {
1040 return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1041 }
1042
1043 MultiIterator operator- (difference_type n) const
1044 {
1045 MultiIterator ret = *this;
1046 ret -= n;
1047 return ret;
1048 }
1049
1050 MultiIterator operator- (multi_difference_type const & d) const
1051 {
1052 MultiIterator ret = *this;
1053 ret -= d;
1054 return ret;
1055 }
1056
1057 reference operator[] (difference_type n) const
1058 {
1059 return this->m_ptr [n*m_stride [level]];
1060 }
1061
1062 reference operator[] (multi_difference_type const & d) const
1063 {
1064 return this->m_ptr [total_stride(d.begin())];
1065 }
1066
1067 next_type begin () const
1068 {
1069 return *this;
1070 }
1071
1072 next_type end () const
1073 {
1074 next_type ret = *this;
1075 ret += m_shape [level-1];
1076 return ret;
1077 }
1078
1079 iterator iteratorForDimension(unsigned int d) const
1080 {
1081 vigra_precondition(d <= level,
1082 "MultiIterator<N>::iteratorForDimension(d): d < N required");
1083 return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
1084 }
1085
1086 template <unsigned int K>
1087 MultiIterator<K+1, T, REFERENCE, POINTER> &
1088 dim()
1089 {
1090 return *this;
1091 }
1092
1093 MultiIterator<1, T, REFERENCE, POINTER> &
1094 dim0() { return *this; }
1095 MultiIterator<2, T, REFERENCE, POINTER> &
1096 dim1() { return *this; }
1097
1098 protected:
1099
1100 difference_type
1101 total_stride(typename multi_difference_type::const_iterator d) const
1102 {
1103 return d[level]*m_stride[level] + base_type::total_stride(d);
1104 }
1105 };
1106
1107 /********************************************************/
1108 /* */
1109 /* MultiIterator<N> */
1110 /* */
1111 /********************************************************/
1112
1113 /** \brief A multi-dimensional hierarchical iterator to be used with
1114 \ref vigra::MultiArrayView if it is not strided.
1115
1116 See \ref MultiIteratorPage for further documentation.
1117
1118 <b>\#include</b> <vigra/multi_iterator.hxx> <br>
1119 Namespace: vigra
1120 */
1121 template <unsigned int N, class T, class REFERENCE, class POINTER>
1122 class MultiIterator
1123 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1124 : public MultiIterator<N-1, T, REFERENCE, POINTER>
1125 #endif
1126 {
1127 public:
1128
1129 /** the type of the parent in the inheritance hierarchy.
1130 */
1131 typedef MultiIterator<N-1, T, REFERENCE, POINTER> base_type;
1132
1133 /** the iterator's level in the dimension hierarchy
1134 */
1135 enum { level = N-1 };
1136
1137 /** the iterator's value type
1138 */
1139 typedef T value_type;
1140
1141 /** reference type (result of operator[])
1142 */
1143 typedef REFERENCE reference;
1144
1145 /** const reference type (result of operator[] const)
1146 */
1147 typedef const value_type &const_reference;
1148
1149 /** pointer type
1150 */
1151 typedef POINTER pointer;
1152
1153 /** const pointer type
1154 */
1155 typedef const value_type *const_pointer;
1156
1157 /** multi difference type
1158 (used for offsetting along all axes simultaneously)
1159 */
1160 typedef typename MultiArrayShape<N>::type multi_difference_type;
1161
1162 /** difference type (used for offsetting)
1163 */
1164 #ifndef DOXYGEN
1165 typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1166 typedef typename stride_traits::stride_type difference_type;
1167 typedef typename stride_traits::stride_array_type difference_array_type;
1168 typedef typename stride_traits::shape_array_type shape_array_type;
1169 #else
1170 typedef MultiArrayIndex difference_type;
1171 #endif
1172
1173 /** the MultiIterator for the next lower dimension.
1174 */
1175 typedef base_type next_type;
1176
1177 /** the 1-dimensional iterator for this iterator hierarchy
1178 (result of iteratorForDimension()).
1179 */
1180 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1181
1182 /** the iterator tag (image traverser)
1183 */
1184 typedef multi_dimensional_traverser_tag iterator_category;
1185
1186 /* use default copy constructor and assignment operator */
1187
1188 /** default constructor.
1189 */
1190 MultiIterator ()
1191 {}
1192
1193 /** construct from pointer, strides (offset of a sample to the
1194 next) for every dimension, and the shape.
1195 */
1196 MultiIterator (pointer ptr,
1197 const difference_array_type & stride,
1198 const shape_array_type & shape)
1199 : base_type (ptr, stride, shape)
1200 {}
1201
1202
1203 /** prefix-increment the iterator in its current dimension
1204 */
1205 void operator++ ()
1206 {
1207 this->m_ptr += this->m_stride [level];
1208 }
1209
1210 /** prefix-decrement the iterator in its current dimension
1211 */
1212 void operator-- ()
1213 {
1214 this->m_ptr -= this->m_stride [level];
1215 }
1216
1217 /** postfix-increment the iterator in its current dimension
1218 */
1219 MultiIterator operator++ (int)
1220 {
1221 MultiIterator ret = *this;
1222 ++(*this);
1223 return ret;
1224 }
1225
1226 /** postfix-decrement the iterator in its current dimension
1227 */
1228 MultiIterator operator-- (int)
1229 {
1230 MultiIterator ret = *this;
1231 --(*this);
1232 return ret;
1233 }
1234
1235 /** increment the iterator in its current dimension
1236 by the given value.
1237 */
1238 MultiIterator & operator+= (difference_type n)
1239 {
1240 this->m_ptr += n * this->m_stride [level];
1241 return *this;
1242 }
1243
1244 /** increment the iterator in all dimensions
1245 by the given offset.
1246 */
1247 MultiIterator & operator+= (multi_difference_type const & d)
1248 {
1249 this->m_ptr += total_stride(d.begin());
1250 return *this;
1251 }
1252
1253 /** decrement the iterator in its current dimension
1254 by the given value.
1255 */
1256 MultiIterator & operator-= (difference_type n)
1257 {
1258 this->m_ptr -= n * this->m_stride [level];
1259 return *this;
1260 }
1261
1262 /** decrement the iterator in all dimensions
1263 by the given offset.
1264 */
1265 MultiIterator & operator-= (multi_difference_type const & d)
1266 {
1267 this->m_ptr -= total_stride(d.begin());
1268 return *this;
1269 }
1270
1271 /** addition within current dimension
1272 */
1273 MultiIterator operator+ (difference_type n) const
1274 {
1275 MultiIterator ret = *this;
1276 ret += n;
1277 return ret;
1278 }
1279
1280 /** addition along all dimensions
1281 */
1282 MultiIterator operator+ (multi_difference_type const & d) const
1283 {
1284 MultiIterator ret = *this;
1285 ret += d;
1286 return ret;
1287 }
1288
1289 /** difference of two iterators in the current dimension.
1290 The result of this operation is undefined if the iterator
1291 doesn't point to element 0 in all dimensions below its current dimension.
1292 */
1293 difference_type operator- (MultiIterator const & d) const
1294 {
1295 return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1296 }
1297
1298 /** subtraction within current dimension
1299 */
1300 MultiIterator operator- (difference_type n) const
1301 {
1302 MultiIterator ret = *this;
1303 ret -= n;
1304 return ret;
1305 }
1306
1307 /** subtraction along all dimensions
1308 */
1309 MultiIterator operator- (multi_difference_type const & d) const
1310 {
1311 MultiIterator ret = *this;
1312 ret -= d;
1313 return ret;
1314 }
1315
1316 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
1317 /** derefenrence item
1318 */
1319 reference operator* () const;
1320
1321 /** get address of current item
1322 */
1323 pointer get () const;
1324
1325 /** call method of current item
1326 */
1327 pointer operator->() const;
1328
1329 /** inequality. True if iterators reference different items.
1330 */
1331 bool operator!= (const MultiIterator &rhs) const;
1332
1333 /** equality. True if iterators reference the same items.
1334 */
1335 bool operator== (const MultiIterator &rhs) const;
1336
1337 /** less than.
1338 */
1339 bool operator< (const MultiIterator &rhs) const;
1340
1341 /** less or equal.
1342 */
1343 bool operator<= (const MultiIterator &rhs) const;
1344
1345 /** greater than.
1346 */
1347 bool operator> (const MultiIterator &rhs) const;
1348
1349 /** greater or equal.
1350 */
1351 bool operator>= (const MultiIterator &rhs) const;
1352 #endif
1353
1354 /** access the array element at the given offset in
1355 the current dimension.
1356 */
1357 reference operator[] (difference_type n) const
1358 {
1359 return this->m_ptr [n* this->m_stride [level]];
1360 }
1361
1362 /** access the array element at the given offset.
1363 */
1364 reference operator[] (multi_difference_type const & d) const
1365 {
1366 return this->m_ptr [total_stride(d.begin())];
1367 }
1368
1369 /** Return the (N-1)-dimensional multi-iterator that points to
1370 the first (N-1)-dimensional subarray of the
1371 N-dimensional array this iterator is referring to.
1372 The result is only valid if this iterator refers to location
1373 0 in <em>all</em> dimensions below its current dimension N,
1374 otherwise it is undefined. Usage:
1375
1376 \code
1377
1378 MultiIterator<2, int> outer = ...; // this iterator
1379
1380 MultiIterator<2, int>::next_type inner = outer.begin();
1381 for(; inner != outer.end(); ++inner)
1382 {
1383 // manipulate current 1D subimage
1384 }
1385 \endcode
1386 */
1387 next_type begin () const
1388 {
1389 return *this;
1390 }
1391
1392 /** Return the (N-1)-dimensional multi-iterator that points beyond
1393 the last (N-1)-dimensional subarray of the
1394 N-dimensional array this iterator is referring to.
1395 The result is only valid if this iterator refers to location
1396 0 in <em>all</em> dimensions below its current dimension N,
1397 otherwise it is undefined.
1398 */
1399 next_type end () const
1400 {
1401 next_type ret = *this;
1402 ret += this->m_shape [level-1];
1403 return ret;
1404 }
1405
1406 /** Get a 1-dimensional, STL-compatible iterator for the
1407 given dimension, pointing to the current element of <TT>this</TT>.
1408 Usage:
1409
1410 \code
1411
1412 MultiIterator<3, int> outer = ...; // this iterator
1413
1414 MultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
1415 MultiIterator<3, int>::iterator end = i + height;
1416 for(; i != end; ++i)
1417 {
1418 // go down the current column starting at the location of 'outer'
1419 }
1420 \endcode
1421 */
1422 iterator iteratorForDimension(unsigned int d) const
1423 {
1424 vigra_precondition(d <= level,
1425 "MultiIterator<N>::iteratorForDimension(d): d < N required");
1426 return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d),0);
1427 }
1428 /** Return the multi-iterator that operates on dimension K in order
1429 to manipulate this dimension directly. Usage:
1430
1431 \code
1432
1433 MultiIterator<3, int> i3 = ...;
1434
1435 i3.template dim<2>()++; // increment outer dimension
1436 i3.template dim<0>()++; // increment inner dimension
1437 \endcode
1438
1439 For convenience, the same functionality is also available
1440 as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
1441
1442 \code
1443
1444 MultiIterator<3, int> i3 = ...;
1445
1446 i3.dim2()++; // increment outer dimension
1447 i3.dim0()++; // increment inner dimension
1448 \endcode
1449 */
1450 template <unsigned int K>
1451 MultiIterator<K+1, T, REFERENCE, POINTER> &
1452 dim()
1453 {
1454 return *this;
1455 }
1456
1457 MultiIterator<1, T, REFERENCE, POINTER> &
1458 dim0() { return *this; }
1459 MultiIterator<2, T, REFERENCE, POINTER> &
1460 dim1() { return *this; }
1461 MultiIterator<3, T, REFERENCE, POINTER> &
1462 dim2() { return *this; }
1463 MultiIterator<4, T, REFERENCE, POINTER> &
1464 dim3() { return *this; }
1465 MultiIterator<5, T, REFERENCE, POINTER> &
1466 dim4() { return *this; }
1467
1468 protected:
1469
1470 difference_type
1471 total_stride(typename multi_difference_type::const_iterator d) const
1472 {
1473 return d[level]*this->m_stride[level] + base_type::total_stride(d);
1474 }
1475
1476 };
1477
1478 /********************************************************/
1479 /* */
1480 /* StridedMultiIterator */
1481 /* */
1482 /********************************************************/
1483
1484 /********************************************************/
1485 /* */
1486 /* StridedMultiIterator<1> */
1487 /* */
1488 /********************************************************/
1489
1490 //
1491 template <class T, class REFERENCE, class POINTER>
1492 class StridedMultiIterator<1, T, REFERENCE, POINTER>
1493 {
1494 public:
1495 enum { level = 0 };
1496 typedef T value_type;
1497 typedef REFERENCE reference;
1498 typedef const value_type &const_reference;
1499 typedef POINTER pointer;
1500 typedef const value_type *const_pointer;
1501 typedef typename MultiArrayShape<1>::type multi_difference_type;
1502 typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1503 typedef typename stride_traits::stride_type difference_type;
1504 typedef typename stride_traits::stride_array_type difference_array_type;
1505 typedef typename stride_traits::shape_array_type shape_array_type;
1506 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1507 typedef std::random_access_iterator_tag iterator_category;
1508
1509 protected:
1510 pointer m_ptr;
1511 difference_type m_stride;
1512
1513 /* use default copy constructor and assignment operator */
1514
1515 public:
1516 StridedMultiIterator ()
1517 : m_ptr (0), m_stride (0)
1518 {}
1519
1520 StridedMultiIterator (pointer ptr,
1521 const difference_array_type & stride,
1522 const shape_array_type &)
1523 : m_ptr (ptr), m_stride (stride [level])
1524 {}
1525
1526 void operator++ ()
1527 {
1528 m_ptr += m_stride;
1529 }
1530
1531 void operator-- ()
1532 {
1533 m_ptr -= m_stride;
1534 }
1535
1536 StridedMultiIterator operator++ (int)
1537 {
1538 StridedMultiIterator ret = *this;
1539 ++(*this);
1540 return ret;
1541 }
1542
1543 StridedMultiIterator operator-- (int)
1544 {
1545 StridedMultiIterator ret = *this;
1546 --(*this);
1547 return ret;
1548 }
1549
1550 StridedMultiIterator &operator+= (difference_type n)
1551 {
1552 m_ptr += n * m_stride;
1553 return *this;
1554 }
1555
1556 StridedMultiIterator & operator+= (multi_difference_type const & d)
1557 {
1558 m_ptr += d[level] * m_stride;
1559 return *this;
1560 }
1561
1562 StridedMultiIterator &operator-= (difference_type n)
1563 {
1564 m_ptr -= n * m_stride;
1565 return *this;
1566 }
1567
1568 StridedMultiIterator & operator-= (multi_difference_type const & d)
1569 {
1570 m_ptr -= d[level] * m_stride;
1571 return *this;
1572 }
1573
1574 StridedMultiIterator operator+ (difference_type n) const
1575 {
1576 StridedMultiIterator ret = *this;
1577 ret += n;
1578 return ret;
1579 }
1580
1581 StridedMultiIterator operator+ (multi_difference_type const & d) const
1582 {
1583 StridedMultiIterator ret = *this;
1584 ret += d;
1585 return ret;
1586 }
1587
1588 difference_type operator- (StridedMultiIterator const & d) const
1589 {
1590 return (m_ptr - d.m_ptr) / m_stride;
1591 }
1592
1593 StridedMultiIterator operator- (difference_type n) const
1594 {
1595 StridedMultiIterator ret = *this;
1596 ret -= n;
1597 return ret;
1598 }
1599
1600 StridedMultiIterator operator- (multi_difference_type const & d) const
1601 {
1602 StridedMultiIterator ret = *this;
1603 ret -= d;
1604 return ret;
1605 }
1606
1607 reference operator[] (difference_type n) const
1608 {
1609 return m_ptr [n*m_stride];
1610 }
1611
1612 reference operator[] (multi_difference_type const & d) const
1613 {
1614 return m_ptr [d[level]*m_stride];
1615 }
1616
1617 reference operator* () const
1618 {
1619 return *m_ptr;
1620 }
1621
1622 pointer get () const
1623 {
1624 return m_ptr;
1625 }
1626
1627 pointer operator->() const
1628 {
1629 return &(operator*());
1630 }
1631
1632 bool operator!= (const StridedMultiIterator &rhs) const
1633 {
1634 return m_ptr != rhs.m_ptr;
1635 }
1636
1637 bool operator== (const StridedMultiIterator &rhs) const
1638 {
1639 return m_ptr == rhs.m_ptr;
1640 }
1641
1642 bool operator< (const StridedMultiIterator &rhs) const
1643 {
1644 return m_ptr < rhs.m_ptr;
1645 }
1646
1647 bool operator<= (const StridedMultiIterator &rhs) const
1648 {
1649 return m_ptr <= rhs.m_ptr;
1650 }
1651
1652 bool operator> (const StridedMultiIterator &rhs) const
1653 {
1654 return m_ptr > rhs.m_ptr;
1655 }
1656
1657 bool operator>= (const StridedMultiIterator &rhs) const
1658 {
1659 return m_ptr >= rhs.m_ptr;
1660 }
1661
1662 iterator iteratorForDimension(unsigned int d) const
1663 {
1664 vigra_precondition(d == 0,
1665 "StridedMultiIterator<1>::iteratorForDimension(d): d == 0 required");
1666 const difference_type stride = 1;
1667 return iterator(m_ptr, &stride, 0);
1668 }
1669
1670 template <unsigned int K>
1671 StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1672 dim()
1673 {
1674 return *this;
1675 }
1676
1677 StridedMultiIterator<1, T, REFERENCE, POINTER> &
1678 dim0() { return *this; }
1679
1680 protected:
1681
1682 difference_type
1683 total_stride(typename multi_difference_type::const_iterator d) const
1684 {
1685 return d[level] * m_stride;
1686 }
1687 };
1688
1689 /********************************************************/
1690 /* */
1691 /* StridedMultiIterator<2> */
1692 /* */
1693 /********************************************************/
1694
1695 //
1696 template <class T, class REFERENCE, class POINTER>
1697 class StridedMultiIterator<2, T, REFERENCE, POINTER>
1698 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1699 : public StridedMultiIterator<1, T, REFERENCE, POINTER>
1700 #endif
1701 {
1702 public:
1703
1704 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
1705 enum { level = 1 };
1706 typedef T value_type;
1707 typedef REFERENCE reference;
1708 typedef const value_type &const_reference;
1709 typedef POINTER pointer;
1710 typedef const value_type *const_pointer;
1711 typedef typename MultiArrayShape<2>::type multi_difference_type;
1712 typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1713 typedef typename stride_traits::stride_type difference_type;
1714 typedef typename stride_traits::stride_array_type difference_array_type;
1715 typedef typename stride_traits::shape_array_type shape_array_type;
1716 typedef base_type next_type;
1717 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1718 typedef multi_dimensional_traverser_tag iterator_category;
1719
1720 protected:
1721 difference_array_type m_stride;
1722 shape_array_type m_shape;
1723
1724 public:
1725 /* use default copy constructor and assignment operator */
1726
1727 StridedMultiIterator ()
1728 : base_type (),
1729 m_stride (0), m_shape (0)
1730 {}
1731
1732 StridedMultiIterator (pointer ptr,
1733 const difference_array_type & stride,
1734 const shape_array_type & shape)
1735 : base_type (ptr, stride, shape),
1736 m_stride (stride), m_shape (shape)
1737 {}
1738
1739 void operator++ ()
1740 {
1741 this->m_ptr += m_stride [level];
1742 }
1743
1744 void operator-- ()
1745 {
1746 this->m_ptr -= m_stride [level];
1747 }
1748
1749 StridedMultiIterator operator++ (int)
1750 {
1751 StridedMultiIterator ret = *this;
1752 ++(*this);
1753 return ret;
1754 }
1755
1756 StridedMultiIterator operator-- (int)
1757 {
1758 StridedMultiIterator ret = *this;
1759 --(*this);
1760 return ret;
1761 }
1762
1763 StridedMultiIterator & operator+= (difference_type n)
1764 {
1765 this->m_ptr += n * m_stride [level];
1766 return *this;
1767 }
1768
1769 StridedMultiIterator & operator+= (multi_difference_type const & d)
1770 {
1771 this->m_ptr += total_stride(d.begin());
1772 return *this;
1773 }
1774
1775 StridedMultiIterator &operator-= (difference_type n)
1776 {
1777 this->m_ptr -= n * m_stride [level];
1778 return *this;
1779 }
1780
1781 StridedMultiIterator & operator-= (multi_difference_type const & d)
1782 {
1783 this->m_ptr -= total_stride(d.begin());
1784 return *this;
1785 }
1786
1787 StridedMultiIterator operator+ (difference_type n) const
1788 {
1789 StridedMultiIterator ret = *this;
1790 ret += n;
1791 return ret;
1792 }
1793
1794 StridedMultiIterator operator+ (multi_difference_type const & d) const
1795 {
1796 StridedMultiIterator ret = *this;
1797 ret += d;
1798 return ret;
1799 }
1800
1801 difference_type operator- (StridedMultiIterator const & d) const
1802 {
1803 return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1804 }
1805
1806 StridedMultiIterator operator- (difference_type n) const
1807 {
1808 StridedMultiIterator ret = *this;
1809 ret -= n;
1810 return ret;
1811 }
1812
1813 StridedMultiIterator operator- (multi_difference_type const & d) const
1814 {
1815 StridedMultiIterator ret = *this;
1816 ret -= d;
1817 return ret;
1818 }
1819
1820 reference operator[] (difference_type n) const
1821 {
1822 return this->m_ptr [n*m_stride [level]];
1823 }
1824
1825 reference operator[] (multi_difference_type const & d) const
1826 {
1827 return this->m_ptr [total_stride(d.begin())];
1828 }
1829
1830 next_type begin () const
1831 {
1832 return *this;
1833 }
1834
1835 next_type end () const
1836 {
1837 next_type ret = *this;
1838 ret += m_shape [level-1];
1839 return ret;
1840 }
1841
1842 iterator iteratorForDimension(unsigned int d) const
1843 {
1844 vigra_precondition(d <= level,
1845 "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
1846 return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
1847 }
1848
1849 template <unsigned int K>
1850 StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1851 dim()
1852 {
1853 return *this;
1854 }
1855
1856 StridedMultiIterator<1, T, REFERENCE, POINTER> &
1857 dim0() { return *this; }
1858 StridedMultiIterator<2, T, REFERENCE, POINTER> &
1859 dim1() { return *this; }
1860
1861 protected:
1862
1863 difference_type
1864 total_stride(typename multi_difference_type::const_iterator d) const
1865 {
1866 return d[level]*m_stride[level] + base_type::total_stride(d);
1867 }
1868 };
1869
1870 /********************************************************/
1871 /* */
1872 /* StridedMultiIterator<N> */
1873 /* */
1874 /********************************************************/
1875
1876 /** \brief A multi-dimensional hierarchical iterator to be used with
1877 \ref vigra::MultiArrayView if it is not strided.
1878
1879 See \ref MultiIteratorPage for further documentation.
1880
1881 <b>\#include</b> <vigra/multi_iterator.hxx> <br>
1882 Namespace: vigra
1883 */
1884 template <unsigned int N, class T, class REFERENCE, class POINTER>
1885 class StridedMultiIterator
1886 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1887 : public StridedMultiIterator<N-1, T, REFERENCE, POINTER>
1888 #endif
1889 {
1890 public:
1891
1892 /** the type of the parent in the inheritance hierarchy.
1893 */
1894 typedef StridedMultiIterator<N-1, T, REFERENCE, POINTER> base_type;
1895
1896 /** the iterator's level in the dimension hierarchy
1897 */
1898 enum { level = N-1 };
1899
1900 /** the iterator's value type
1901 */
1902 typedef T value_type;
1903
1904 /** reference type (result of operator[])
1905 */
1906 typedef REFERENCE reference;
1907
1908 /** const reference type (result of operator[] const)
1909 */
1910 typedef const value_type &const_reference;
1911
1912 /** pointer type
1913 */
1914 typedef POINTER pointer;
1915
1916 /** const pointer type
1917 */
1918 typedef const value_type *const_pointer;
1919
1920 /** multi difference type
1921 (used for offsetting along all axes simultaneously)
1922 */
1923 typedef typename MultiArrayShape<N>::type multi_difference_type;
1924
1925 /** difference type (used for offsetting)
1926 */
1927 #ifndef DOXYGEN
1928 typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1929 typedef typename stride_traits::stride_type difference_type;
1930 typedef typename stride_traits::stride_array_type difference_array_type;
1931 #else
1932 typedef MultiArrayIndex difference_type;
1933 #endif
1934
1935 /** the StridedMultiIterator for the next lower dimension.
1936 */
1937 typedef base_type next_type;
1938
1939 /** the 1-dimensional iterator for this iterator hierarchy
1940 (result of iteratorForDimension()).
1941 */
1942 typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1943
1944 /** the iterator tag (image traverser)
1945 */
1946 typedef multi_dimensional_traverser_tag iterator_category;
1947
1948 /* use default copy constructor and assignment operator */
1949
1950 /** default constructor.
1951 */
1952 StridedMultiIterator ()
1953 {}
1954
1955 /** construct from pointer, strides (offset of a sample to the
1956 next) for every dimension, and the shape.
1957 */
1958 StridedMultiIterator (pointer ptr,
1959 const difference_array_type & stride,
1960 const difference_array_type & shape)
1961 : base_type (ptr, stride, shape)
1962 {}
1963
1964
1965 /** prefix-increment the iterator in its current dimension
1966 */
1967 void operator++ ()
1968 {
1969 this->m_ptr += this->m_stride [level];
1970 }
1971
1972 /** prefix-decrement the iterator in its current dimension
1973 */
1974 void operator-- ()
1975 {
1976 this->m_ptr -= this->m_stride [level];
1977 }
1978
1979 /** postfix-increment the iterator in its current dimension
1980 */
1981 StridedMultiIterator operator++ (int)
1982 {
1983 StridedMultiIterator ret = *this;
1984 ++(*this);
1985 return ret;
1986 }
1987
1988 /** postfix-decrement the iterator in its current dimension
1989 */
1990 StridedMultiIterator operator-- (int)
1991 {
1992 StridedMultiIterator ret = *this;
1993 --(*this);
1994 return ret;
1995 }
1996
1997 /** increment the iterator in its current dimension
1998 by the given value.
1999 */
2000 StridedMultiIterator & operator+= (difference_type n)
2001 {
2002 this->m_ptr += n * this->m_stride [level];
2003 return *this;
2004 }
2005
2006 /** increment the iterator in all dimensions
2007 by the given offset.
2008 */
2009 StridedMultiIterator & operator+= (multi_difference_type const & d)
2010 {
2011 this->m_ptr += total_stride(d.begin());
2012 return *this;
2013 }
2014
2015 /** decrement the iterator in its current dimension
2016 by the given value.
2017 */
2018 StridedMultiIterator & operator-= (difference_type n)
2019 {
2020 this->m_ptr -= n * this->m_stride [level];
2021 return *this;
2022 }
2023
2024 /** decrement the iterator in all dimensions
2025 by the given offset.
2026 */
2027 StridedMultiIterator & operator-= (multi_difference_type const & d)
2028 {
2029 this->m_ptr -= total_stride(d.begin());
2030 return *this;
2031 }
2032
2033 /** addition within current dimension
2034 */
2035 StridedMultiIterator operator+ (difference_type n) const
2036 {
2037 StridedMultiIterator ret = *this;
2038 ret += n;
2039 return ret;
2040 }
2041
2042 /** addition along all dimensions
2043 */
2044 StridedMultiIterator operator+ (multi_difference_type const & d) const
2045 {
2046 StridedMultiIterator ret = *this;
2047 ret += d;
2048 return ret;
2049 }
2050
2051 /** difference of two iterators in the current dimension.
2052 The result of this operation is undefined if the iterator
2053 doesn't point to element 0 in all dimensions below its current dimension.
2054 */
2055 difference_type operator- (StridedMultiIterator const & d) const
2056 {
2057 return (this->m_ptr - d.m_ptr) / this->m_stride[level];
2058 }
2059
2060 /** subtraction within current dimension
2061 */
2062 StridedMultiIterator operator- (difference_type n) const
2063 {
2064 StridedMultiIterator ret = *this;
2065 ret -= n;
2066 return ret;
2067 }
2068
2069 /** subtraction along all dimensions
2070 */
2071 StridedMultiIterator operator- (multi_difference_type const & d) const
2072 {
2073 StridedMultiIterator ret = *this;
2074 ret -= d;
2075 return ret;
2076 }
2077
2078 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
2079 /** derefenrence item
2080 */
2081 reference operator* () const;
2082
2083 /** get address of current item
2084 */
2085 pointer get () const;
2086
2087 /** call method of current item
2088 */
2089 pointer operator->() const;
2090
2091 /** inequality. True if iterators reference different items.
2092 */
2093 bool operator!= (const StridedMultiIterator &rhs) const;
2094
2095 /** equality. True if iterators reference the same items.
2096 */
2097 bool operator== (const StridedMultiIterator &rhs) const;
2098
2099 /** less than.
2100 */
2101 bool operator< (const StridedMultiIterator &rhs) const;
2102
2103 /** less or equal.
2104 */
2105 bool operator<= (const StridedMultiIterator &rhs) const;
2106
2107 /** greater than.
2108 */
2109 bool operator> (const StridedMultiIterator &rhs) const;
2110
2111 /** greater or equal.
2112 */
2113 bool operator>= (const StridedMultiIterator &rhs) const;
2114 #endif
2115
2116 /** access the array element at the given offset in
2117 the current dimension.
2118 */
2119 reference operator[] (difference_type n) const
2120 {
2121 return this->m_ptr [n* this->m_stride [level]];
2122 }
2123
2124 /** access the array element at the given offset.
2125 */
2126 reference operator[] (multi_difference_type const & d) const
2127 {
2128 return this->m_ptr [total_stride(d.begin())];
2129 }
2130
2131 /** Return the (N-1)-dimensional multi-iterator that points to
2132 the first (N-1)-dimensional subarray of the
2133 N-dimensional array this iterator is referring to.
2134 The result is only valid if this iterator refers to location
2135 0 in <em>all</em> dimensions below its current dimension N,
2136 otherwise it is undefined. Usage:
2137
2138 \code
2139
2140 StridedMultiIterator<2, int> outer = ...; // this iterator
2141
2142 StridedMultiIterator<2, int>::next_type inner = outer.begin();
2143 for(; inner != outer.end(); ++inner)
2144 {
2145 // manipulate current 1D subimage
2146 }
2147 \endcode
2148 */
2149 next_type begin () const
2150 {
2151 return *this;
2152 }
2153
2154 /** Return the (N-1)-dimensional multi-iterator that points beyond
2155 the last (N-1)-dimensional subarray of the
2156 N-dimensional array this iterator is referring to.
2157 The result is only valid if this iterator refers to location
2158 0 in <em>all</em> dimensions below its current dimension N,
2159 otherwise it is undefined.
2160 */
2161 next_type end () const
2162 {
2163 next_type ret = *this;
2164 ret += this->m_shape [level-1];
2165 return ret;
2166 }
2167
2168 /** Get a 1-dimensional, STL-compatible iterator for the
2169 given dimension, pointing to the current element of <TT>this</TT>.
2170 Usage:
2171
2172 \code
2173
2174 StridedMultiIterator<3, int> outer = ...; // this iterator
2175
2176 StridedMultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
2177 StridedMultiIterator<3, int>::iterator end = i + height;
2178 for(; i != end; ++i)
2179 {
2180 // go down the current column starting at the location of 'outer'
2181 }
2182 \endcode
2183 */
2184 iterator iteratorForDimension(unsigned int d) const
2185 {
2186 vigra_precondition(d <= level,
2187 "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
2188 return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d),0);
2189 }
2190 /** Return the multi-iterator that operates on dimension K in order
2191 to manipulate this dimension directly. Usage:
2192
2193 \code
2194
2195 StridedMultiIterator<3, int> i3 = ...;
2196
2197 i3.template dim<2>()++; // increment outer dimension
2198 i3.template dim<0>()++; // increment inner dimension
2199 \endcode
2200
2201 For convenience, the same functionality is also available
2202 as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
2203
2204 \code
2205
2206 StridedMultiIterator<3, int> i3 = ...;
2207
2208 i3.dim2()++; // increment outer dimension
2209 i3.dim0()++; // increment inner dimension
2210 \endcode
2211 */
2212 template <unsigned int K>
2213 StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
2214 dim()
2215 {
2216 return *this;
2217 }
2218
2219 StridedMultiIterator<1, T, REFERENCE, POINTER> &
2220 dim0() { return *this; }
2221 StridedMultiIterator<2, T, REFERENCE, POINTER> &
2222 dim1() { return *this; }
2223 StridedMultiIterator<3, T, REFERENCE, POINTER> &
2224 dim2() { return *this; }
2225 StridedMultiIterator<4, T, REFERENCE, POINTER> &
2226 dim3() { return *this; }
2227 StridedMultiIterator<5, T, REFERENCE, POINTER> &
2228 dim4() { return *this; }
2229
2230 protected:
2231
2232 difference_type
2233 total_stride(typename multi_difference_type::const_iterator d) const
2234 {
2235 return d[level]*this->m_stride[level] + base_type::total_stride(d);
2236 }
2237
2238 };
2239
2240 //@}
2241
2242 } // namespace vigra
2243
2244 namespace std {
2245
2246 template <unsigned int N, class T, class REFERENCE, class POINTER>
2247 ostream & operator<<(ostream & o, vigra::StridedScanOrderIterator<N, T, REFERENCE, POINTER> const & i)
2248 {
2249 o << *i;
2250 return o;
2251 }
2252
2253 } // namespace std
2254
2255 #endif // VIGRA_MULTI_ITERATOR_HXX

© 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.10.0 (Mon Nov 18 2013)