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>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayView or \ref vigra::MultiIterator</em>
453 <LI> \ref vigra::MultiIterator
454      <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArrayView</em>
455 <LI> \ref vigra::StridedMultiIterator
456      <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayView</em>
457 <LI> \ref vigra::StridedScanOrderIterator
458      <BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \ref vigra::MultiArrayView</em>
459 <LI> \ref vigra::CoupledScanOrderIterator
460      <BR>&nbsp;&nbsp;&nbsp;<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