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