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

vigra/multi_iterator.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*     Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe       */
    00004 /*                                                                      */
    00005 /*    This file is part of the VIGRA computer vision library.           */
    00006 /*    ( Version 1.3.0, Sep 10 2004 )                                    */
    00007 /*    The VIGRA Website is                                              */
    00008 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00009 /*    Please direct questions, bug reports, and contributions to        */
    00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00011 /*        vigra@informatik.uni-hamburg.de                               */
    00012 /*                                                                      */
    00013 /*    Permission is hereby granted, free of charge, to any person       */
    00014 /*    obtaining a copy of this software and associated documentation    */
    00015 /*    files (the "Software"), to deal in the Software without           */
    00016 /*    restriction, including without limitation the rights to use,      */
    00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00018 /*    sell copies of the Software, and to permit persons to whom the    */
    00019 /*    Software is furnished to do so, subject to the following          */
    00020 /*    conditions:                                                       */
    00021 /*                                                                      */
    00022 /*    The above copyright notice and this permission notice shall be    */
    00023 /*    included in all copies or substantial portions of the             */
    00024 /*    Software.                                                         */
    00025 /*                                                                      */
    00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00034 /*                                                                      */
    00035 /************************************************************************/
    00036
    00037
    00038 #ifndef VIGRA_MULTI_ITERATOR_HXX
    00039 #define VIGRA_MULTI_ITERATOR_HXX
    00040
    00041 #include <sys/types.h>
    00042 #include "tinyvector.hxx"
    00043 #include "iteratortags.hxx"
    00044
    00045 namespace vigra {
    00046
    00047
    00048 template <unsigned int N, class T,
    00049           class REFERENCE = T &, class POINTER = T *> class MultiIterator;
    00050 template <unsigned int N, class T,
    00051           class REFERENCE = T &, class POINTER = T *> class StridedMultiIterator;
    00052
    00053 /** \page MultiIteratorPage  Multi-dimensional Array Iterators
    00054
    00055     General iterators for arrays of arbitrary dimension.
    00056
    00057
    00058 <p>
    00059 <UL style="list-style-image:url(documents/bullet.gif)">
    00060 <LI> \ref vigra::MultiArrayShape
    00061      <BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayView or \ref vigra::MultiIterator</em>
    00062 <LI> \ref vigra::MultiIterator
    00063      <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArrayView</em>
    00064 <LI> \ref vigra::StridedMultiIterator
    00065      <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayView</em>
    00066 </UL>
    00067 </p>
    00068
    00069 <p>
    00070     The Multidimensional Iterator concept allows navigation on arrays
    00071     of arbitrary dimension. It provides two modes of iteration:
    00072     <em>direct traveral</em>, and <em>hierarchical traversal</em>.
    00073     In general, hierarchical traversal will be faster, while only
    00074     direct traversal allows for true random access in all dimensions.
    00075     Via the <tt>dim<K>()</tt> function, operations applying to a particular
    00076     dimension can be used in the direct traversal mode. In contrast,
    00077     direct traversal functions should not be used in the hierarchical mode
    00078     because the hierarchical functions are only well-defined if the
    00079     iterator points to element 0 in all dimensions below its current dimension.
    00080     The current dimension of a <tt>MultiIterator<N, ...></tt> is <tt>N-1</tt>.
    00081 </p>
    00082 <h3>Gerneral Requirements for MultiIterator</h3>
    00083 <p>
    00084 <table border=2 cellspacing=0 cellpadding=2 width="100%">
    00085 <tr><th colspan=2>
    00086     Local Types
    00087     </th><th>
    00088     Meaning
    00089     </th>
    00090 </tr>
    00091 <tr><td colspan=2>
    00092     <tt>MultiIterator::value_type</tt></td><td>the underlying arrays's pixel type</td>
    00093 </tr>
    00094 <tr><td colspan=2>
    00095     <tt>MultiIterator::reference</tt></td>
    00096     <td>the iterator's reference type (return type of <TT>*iter</TT>). Will be
    00097     <tt>value_type &</tt> for a mutable iterator, and convertible to
    00098     <tt>value_type const &</tt> for a const iterator.</td>
    00099 </tr>
    00100 <tr><td colspan=2>
    00101     <tt>MultiIterator::pointer</tt></td>
    00102     <td>the iterator's pointer type (return type of <TT>iter.operator->()</TT>). Will be
    00103     <tt>value_type *</tt> for a mutable iterator, and convertible to
    00104     <tt>value_type const *</tt> for a const iterator.</td>
    00105 </tr>
    00106 <tr><td colspan=2>
    00107     <tt>MultiIterator::iterator_category</tt></td>
    00108     <td>the iterator tag (<tt>vigra::multi_dimensional_traverser_tag</tt>)</td>
    00109 </tr>
    00110 <tr><th>
    00111     Operation
    00112     </th><th>
    00113     Result
    00114     </th><th>
    00115     Semantics
    00116     </th>
    00117 </tr>
    00118 <tr><td colspan=2>
    00119     <tt>MultiIterator k;</tt></td><td>default constructor</td>
    00120 </tr>
    00121 <tr><td colspan=2>
    00122     <tt>MultiIterator k(i);</tt></td><td>copy constructor</td>
    00123 </tr>
    00124 <tr>
    00125     <td><tt>k = i</tt></td>
    00126     <td><tt>MultiIterator &</tt></td><td>assignment</td>
    00127 </tr>
    00128 <tr>
    00129     <td><tt>i == j</tt></td><td><tt>bool</tt></td>
    00130     <td>equality (iterators point to the same element)</td>
    00131 </tr>
    00132 <tr>
    00133     <td><tt>i != j</tt></td><td><tt>bool</tt></td>
    00134     <td>inequality (iterators don't point to the same element)</td>
    00135 </tr>
    00136 <tr>
    00137     <td><tt>*i</tt></td><td><tt>MultiIterator::reference</tt></td>
    00138     <td>access the current element</td>
    00139 </tr>
    00140 <tr>
    00141     <td><tt>i->member()</tt></td><td>depends on operation</td>
    00142     <td>call member function of underlying pixel type via <tt>operator-></tt> of iterator</td>
    00143 </tr>
    00144 </table>
    00145 </p>
    00146 <h3>Requirements for Direct Traversal</h3>
    00147 <p>
    00148 <table border=2 cellspacing=0 cellpadding=2 width="100%">
    00149 <tr><th colspan=2>
    00150     Local Types
    00151     </th><th>
    00152     Meaning
    00153     </th>
    00154 </tr>
    00155 <tr><td colspan=2>
    00156     <tt>MultiIterator::multi_difference_type</tt></td>
    00157     <td>the iterator's multi-dimensional difference type (<TT>TinyVector<MultiArrayIndex, N></TT>)</td>
    00158 </tr>
    00159 <tr><th>
    00160     Operation
    00161     </th><th>
    00162     Result
    00163     </th><th>
    00164     Semantics
    00165     </th>
    00166 </tr>
    00167 <tr>
    00168     <td><tt>i += diff</tt></td><td><tt>MultiIterator &</tt></td>
    00169     <td>add offset to current position</td>
    00170 </tr>
    00171 <tr>
    00172     <td><tt>i -= diff</tt></td><td><tt>MultiIterator &</tt></td>
    00173     <td>subtract offset from current position</td>
    00174 </tr>
    00175 <tr>
    00176     <td><tt>i + diff</tt></td><td><tt>MultiIterator</tt></td>
    00177     <td>create traverser by adding offset</td>
    00178 </tr>
    00179 <tr>
    00180     <td><tt>i - diff</tt></td><td><tt>MultiIterator</tt></td>
    00181     <td>create traverser by subtracting offset</td>
    00182 </tr>
    00183 <tr>
    00184     <td><tt>i[diff]</tt></td><td><tt>MultiIterator::reference</tt></td>
    00185     <td>access element at offset <tt>diff</tt></td>
    00186 </tr>
    00187 <tr>
    00188     <td><tt>i.dim<K>()</tt></td><td><tt>MultiIterator<K+1, T, ...></tt></td>
    00189     <td>Access the traverser with the current dimension set to K. Typically used to call
    00190         navigation functions referring to a particular dimension.<br>
    00191         Example (assuming <tt>i, j</tt> are 3-dimensional):<br>
    00192         \code
    00193         i.dim<0>()++;   // increment dimension 0
    00194         i.dim<1>()++;   // increment dimension 1
    00195         i.dim<2>()++;   // increment dimension 2
    00196
    00197         j += MultiIterator::multi_difference_type(1,1,1);    // same effect
    00198         \endcode
    00199     </td>
    00200 </tr>
    00201 <tr><td colspan=3>
    00202        <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
    00203        <tt>diff</tt> is of type <tt>MultiIterator::multi_difference_type</tt><br>
    00204        <tt>K</tt> is an integer compile-time constant
    00205     </td>
    00206 </tr>
    00207 </table>
    00208 </p>
    00209 <p>
    00210 Note that it is impossible to support an <tt>operator-</tt> between two iterators which returns
    00211 a <tt>MultiIterator::multi_difference_type</tt> because it is impossible to decide to which
    00212 dimension a difference applies. Consider for example, a 2-dimensional iterator <tt>i</tt>, and
    00213 let <tt>j = i + multi_difference_type(width, 0)</tt>, <tt>k = i + multi_difference_type(0,1)</tt>,
    00214 where <tt>width</tt> is the array's total width. In general, <tt>j</tt> and <tt>k</tt> point to
    00215 the same memory location, so that the two cases cannot easily be distinguished (it is possible,
    00216 but iterator performance will suffer significantly, as is experienced with
    00217 \ref vigra::ImageIterator where differencing is allowed).
    00218 </p>
    00219
    00220 <h3>Requirements for Hierarchical Traversal</h3>
    00221 <p>
    00222 <table border=2 cellspacing=0 cellpadding=2 width="100%">
    00223 <tr><th colspan=2>
    00224     Local Types
    00225     </th><th>
    00226     Meaning
    00227     </th>
    00228 </tr>
    00229 <tr><td colspan=2>
    00230     <tt>MultiIterator::difference_type</tt></td>
    00231     <td>the iterator's difference type (<TT>MultiArrayIndex</TT>)</td>
    00232 </tr>
    00233 <tr><td colspan=2>
    00234     <tt>MultiIterator::next_type</tt></td><td>type of the next iterator
    00235        (referring to the next lower dimension) in the hierarchy</td>
    00236 </tr>
    00237 <tr><th>
    00238     Operation
    00239     </th><th>
    00240     Result
    00241     </th><th>
    00242     Semantics
    00243     </th>
    00244 </tr>
    00245 <tr>
    00246     <td><tt>++i</tt></td><td><tt>MultiIterator &</tt></td>
    00247     <td>pre-increment iterator in its current dimension</td>
    00248 </tr>
    00249 <tr>
    00250     <td><tt>i++</tt></td><td><tt>MultiIterator</tt></td>
    00251     <td>post-increment iterator in its current dimension</td>
    00252 </tr>
    00253 <tr>
    00254     <td><tt>--i</tt></td><td><tt>MultiIterator &</tt></td>
    00255     <td>pre-decrement iterator in its current dimension</td>
    00256 </tr>
    00257 <tr>
    00258     <td><tt>i--</tt></td><td><tt>MultiIterator</tt></td>
    00259     <td>post-decrement iterator in its current dimension</td>
    00260 </tr>
    00261 <tr>
    00262     <td><tt>i += d</tt></td><td><tt>MultiIterator &</tt></td>
    00263     <td>add <tt>d</tt> in current dimension</td>
    00264 </tr>
    00265 <tr>
    00266     <td><tt>i -= d</tt></td><td><tt>MultiIterator &</tt></td>
    00267     <td>subtract <tt>d</tt> in from dimension</td>
    00268 </tr>
    00269 <tr>
    00270     <td><tt>i + d</tt></td><td><tt>MultiIterator</tt></td>
    00271     <td>create new iterator by adding <tt>d</tt> in current dimension</td>
    00272 </tr>
    00273 <tr>
    00274     <td><tt>i - d</tt></td><td><tt>MultiIterator</tt></td>
    00275     <td>create new iterator by subtracting <tt>d</tt> in current dimension</td>
    00276 </tr>
    00277 <tr>
    00278     <td><tt>i - j</tt></td><td><tt>difference_type</tt></td>
    00279     <td>difference of <tt>i</tt> and <tt>j</tt> in the current dimension<br>
    00280     <em>Note:</em> The result of this operation is undefined if the iterator
    00281     doesn't point to element 0 in all dimensions below its current dimension.</td>
    00282 </tr>
    00283 <tr>
    00284     <td><tt>i < j</tt></td><td><tt>bool</tt></td>
    00285     <td><tt>i - j < 0</tt><br>
    00286     <em>Note:</em> The result of this operation is undefined if the iterator
    00287     doesn't point to element 0 in all dimensions below its current dimension.</td>
    00288 </tr>
    00289 <tr>
    00290     <td><tt>i[d]</tt></td><td><tt>MultiIterator::reference</tt></td>
    00291     <td>access element by adding offset <tt>d</tt> in current dimension</td>
    00292 </tr>
    00293 <tr>
    00294     <td><tt>i.begin()</tt></td><td><tt>next_type</tt></td>
    00295     <td>create the hierarchical iterator poiting to the first element in the
    00296     next lower dimension.<br>
    00297     <em>Note:</em> The result of this operation is undefined if the iterator
    00298     doesn't point to element 0 in all dimensions below its current dimension.<br>
    00299     Usage:<br>
    00300     \code
    00301     MultiIterator<3, int> i3 = ..., end3 = ...;
    00302     for(; i3 != end3; ++i3)
    00303     {
    00304         MultiIterator<3, int>::next_type i2 = i3.begin(), end2 = i3.end();
    00305         for(; i2 != end2; ++i2)
    00306         {
    00307             MultiIterator<3, int>::next_type::next_type i1 = i2.begin(), end1 = i2.end();
    00308             for(; i1 != end1; ++i1)
    00309             {
    00310                 ... // do something with the current element
    00311             }
    00312         }
    00313     }
    00314
    00315     \endcode
    00316     </td>
    00317 </tr>
    00318 <tr>
    00319     <td><tt>i.end()</tt></td><td><tt>next_type</tt></td>
    00320     <td>create the hierarchical iterator poiting to the past-the-end location in the
    00321     next lower dimension.<br>
    00322     <em>Note:</em> The result of this operation is undefined if the iterator
    00323     doesn't point to element 0 in all dimensions below its current dimension.</td>
    00324 </tr>
    00325 <tr><td colspan=3>
    00326        <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
    00327        <tt>d</tt> is of type <tt>MultiIterator::difference_type</tt>
    00328     </td>
    00329 </tr>
    00330 </table>
    00331 </p>
    00332
    00333 */
    00334
    00335 /** \addtogroup MultiIteratorGroup  Multi-dimensional Array Iterators
    00336
    00337     \brief General iterators for arrays of arbitrary dimension.
    00338 */
    00339 //@{
    00340
    00341     /** Index type for a single dimension of a MultiArrayView or
    00342         MultiArray.
    00343     */
    00344 typedef std::ptrdiff_t MultiArrayIndex;
    00345
    00346     /** Traits class for the difference type of all MultiIterator, MultiArrayView, and
    00347         MultiArray variants.
    00348     */
    00349 template <unsigned int N>
    00350 class MultiArrayShape
    00351 {
    00352   public:
    00353         /** The difference type of all MultiIterator, MultiArrayView, and
    00354             MultiArray variants.
    00355         */
    00356     typedef TinyVector<MultiArrayIndex, N> type;
    00357 };
    00358
    00359 /********************************************************/
    00360 /*                                                      */
    00361 /*                      MultiIterator                   */
    00362 /*                                                      */
    00363 /********************************************************/
    00364
    00365 template <unsigned int N, class T, class REFERENCE, class POINTER>
    00366 class MultiIterator;
    00367
    00368 /********************************************************/
    00369 /*                                                      */
    00370 /*                   MultiIterator<1>                   */
    00371 /*                                                      */
    00372 /********************************************************/
    00373
    00374 //
    00375 template <class T, class REFERENCE, class POINTER>
    00376 class MultiIterator<1, T, REFERENCE, POINTER>
    00377 {
    00378   public:
    00379     enum { level = 0 };
    00380     typedef T value_type;
    00381     typedef REFERENCE reference;
    00382     typedef const value_type &const_reference;
    00383     typedef POINTER pointer;
    00384     typedef const value_type *const_pointer;
    00385     typedef typename MultiArrayShape<1>::type multi_difference_type;
    00386     typedef MultiArrayIndex difference_type;
    00387     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
    00388     typedef std::random_access_iterator_tag iterator_category;
    00389
    00390   protected:
    00391     pointer m_ptr;
    00392
    00393   public:
    00394     MultiIterator ()
    00395         : m_ptr (0)
    00396     {}
    00397
    00398     MultiIterator (pointer ptr,
    00399           const difference_type *,
    00400           const difference_type *)
    00401         : m_ptr (ptr)
    00402     {}
    00403
    00404     void operator++ ()
    00405     {
    00406         ++m_ptr;
    00407     }
    00408
    00409     void operator-- ()
    00410     {
    00411         --m_ptr;
    00412     }
    00413
    00414     MultiIterator operator++ (int)
    00415     {
    00416         MultiIterator ret = *this;
    00417         ++(*this);
    00418         return ret;
    00419     }
    00420
    00421     MultiIterator operator-- (int)
    00422     {
    00423         MultiIterator ret = *this;
    00424         --(*this);
    00425         return ret;
    00426     }
    00427
    00428     MultiIterator &operator+= (difference_type n)
    00429     {
    00430         m_ptr += n;
    00431         return *this;
    00432     }
    00433
    00434     MultiIterator & operator+= (multi_difference_type const & d)
    00435     {
    00436         m_ptr += d[level];
    00437         return *this;
    00438     }
    00439
    00440     MultiIterator &operator-= (difference_type n)
    00441     {
    00442         m_ptr -= n;
    00443         return *this;
    00444     }
    00445
    00446     MultiIterator & operator-= (multi_difference_type const & d)
    00447     {
    00448         m_ptr -= d[level];
    00449         return *this;
    00450     }
    00451
    00452     MultiIterator operator+ (difference_type n) const
    00453     {
    00454         MultiIterator ret = *this;
    00455         ret += n;
    00456         return ret;
    00457     }
    00458
    00459     MultiIterator operator+ (multi_difference_type const & d) const
    00460     {
    00461         MultiIterator ret = *this;
    00462         ret += d;
    00463         return ret;
    00464     }
    00465
    00466     difference_type operator- (MultiIterator const & d) const
    00467     {
    00468         return (m_ptr - d.m_ptr);
    00469     }
    00470
    00471     MultiIterator operator- (difference_type n) const
    00472     {
    00473         MultiIterator ret = *this;
    00474         ret -= n;
    00475         return ret;
    00476     }
    00477
    00478     MultiIterator operator- (multi_difference_type const & d) const
    00479     {
    00480         MultiIterator ret = *this;
    00481         ret -= d;
    00482         return ret;
    00483     }
    00484
    00485     reference operator[] (difference_type n) const
    00486     {
    00487         return m_ptr [n];
    00488     }
    00489
    00490     reference operator[] (multi_difference_type const & d) const
    00491     {
    00492         return m_ptr [d[level]];
    00493     }
    00494
    00495     reference operator* () const
    00496     {
    00497         return *m_ptr;
    00498     }
    00499
    00500     pointer get () const
    00501     {
    00502         return m_ptr;
    00503     }
    00504
    00505     pointer operator->() const
    00506     {
    00507         return &(operator*());
    00508     }
    00509
    00510     bool operator!= (const MultiIterator &rhs) const
    00511     {
    00512         return m_ptr != rhs.m_ptr;
    00513     }
    00514
    00515     bool operator== (const MultiIterator &rhs) const
    00516     {
    00517         return m_ptr == rhs.m_ptr;
    00518     }
    00519
    00520     bool operator< (const MultiIterator &rhs) const
    00521     {
    00522         return m_ptr < rhs.m_ptr;
    00523     }
    00524
    00525     bool operator<= (const MultiIterator &rhs) const
    00526     {
    00527         return m_ptr <= rhs.m_ptr;
    00528     }
    00529
    00530     bool operator> (const MultiIterator &rhs) const
    00531     {
    00532         return m_ptr > rhs.m_ptr;
    00533     }
    00534
    00535     bool operator>= (const MultiIterator &rhs) const
    00536     {
    00537         return m_ptr >= rhs.m_ptr;
    00538     }
    00539
    00540     iterator iteratorForDimension(unsigned int d) const
    00541     {
    00542         vigra_precondition(d == 0,
    00543             "MultiIterator<1>::iteratorForDimension(d): d == 0 required");
    00544         const difference_type stride = 1;
    00545         return iterator(m_ptr, &stride, 0);
    00546     }
    00547
    00548     template <unsigned int K>
    00549     MultiIterator<K+1, T, REFERENCE, POINTER> &
    00550     dim()
    00551     {
    00552         return *this;
    00553     }
    00554
    00555     MultiIterator<1, T, REFERENCE, POINTER> &
    00556     dim0() { return *this; }
    00557
    00558   protected:
    00559
    00560     difference_type
    00561     total_stride(typename multi_difference_type::const_iterator d) const
    00562     {
    00563         return d[level];
    00564     }
    00565 };
    00566
    00567 /********************************************************/
    00568 /*                                                      */
    00569 /*                   MultiIterator<2>                   */
    00570 /*                                                      */
    00571 /********************************************************/
    00572
    00573 //
    00574 template <class T, class REFERENCE, class POINTER>
    00575 class MultiIterator<2, T, REFERENCE, POINTER>
    00576 : public MultiIterator<1, T, REFERENCE, POINTER>
    00577 {
    00578   public:
    00579
    00580     typedef MultiIterator<1, T, REFERENCE, POINTER> base_type;
    00581     enum { level = 1 };
    00582     typedef T value_type;
    00583     typedef REFERENCE reference;
    00584     typedef const value_type &const_reference;
    00585     typedef POINTER pointer;
    00586     typedef const value_type *const_pointer;
    00587     typedef typename MultiArrayShape<2>::type multi_difference_type;
    00588     typedef MultiArrayIndex difference_type;
    00589     typedef base_type next_type;
    00590     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
    00591     typedef multi_dimensional_traverser_tag iterator_category;
    00592
    00593   protected:
    00594     const difference_type *m_stride;
    00595     const difference_type *m_shape;
    00596
    00597   public:
    00598     /* use default copy constructor and assignment operator */
    00599
    00600     MultiIterator ()
    00601         : base_type (),
    00602           m_stride (0), m_shape (0)
    00603     {}
    00604
    00605     MultiIterator (pointer ptr,
    00606           const difference_type *stride,
    00607           const difference_type *shape)
    00608         : base_type (ptr, stride, shape),
    00609           m_stride (stride), m_shape (shape)
    00610     {}
    00611
    00612     void operator++ ()
    00613     {
    00614         this->m_ptr += m_stride [level];
    00615     }
    00616
    00617     void operator-- ()
    00618     {
    00619         this->m_ptr -= m_stride [level];
    00620     }
    00621
    00622     MultiIterator operator++ (int)
    00623     {
    00624         MultiIterator ret = *this;
    00625         ++(*this);
    00626         return ret;
    00627     }
    00628
    00629     MultiIterator operator-- (int)
    00630     {
    00631         MultiIterator ret = *this;
    00632         --(*this);
    00633         return ret;
    00634     }
    00635
    00636     MultiIterator & operator+= (difference_type n)
    00637     {
    00638         this->m_ptr += n * m_stride [level];
    00639         return *this;
    00640     }
    00641
    00642     MultiIterator & operator+= (multi_difference_type const & d)
    00643     {
    00644         this->m_ptr += total_stride(d.begin());
    00645         return *this;
    00646     }
    00647
    00648     MultiIterator  &operator-= (difference_type n)
    00649     {
    00650         this->m_ptr -= n * m_stride [level];
    00651         return *this;
    00652     }
    00653
    00654     MultiIterator & operator-= (multi_difference_type const & d)
    00655     {
    00656         this->m_ptr -= total_stride(d.begin());
    00657         return *this;
    00658     }
    00659
    00660     MultiIterator operator+ (difference_type n) const
    00661     {
    00662         MultiIterator ret = *this;
    00663         ret += n;
    00664         return ret;
    00665     }
    00666
    00667     MultiIterator operator+ (multi_difference_type const & d) const
    00668     {
    00669         MultiIterator ret = *this;
    00670         ret += d;
    00671         return ret;
    00672     }
    00673
    00674     difference_type operator- (MultiIterator const & d) const
    00675     {
    00676         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
    00677     }
    00678
    00679     MultiIterator operator- (difference_type n) const
    00680     {
    00681         MultiIterator ret = *this;
    00682         ret -= n;
    00683         return ret;
    00684     }
    00685
    00686     MultiIterator operator- (multi_difference_type const & d) const
    00687     {
    00688         MultiIterator ret = *this;
    00689         ret -= d;
    00690         return ret;
    00691     }
    00692
    00693     reference operator[] (difference_type n) const
    00694     {
    00695         return this->m_ptr [n*m_stride [level]];
    00696     }
    00697
    00698     reference operator[] (multi_difference_type const & d) const
    00699     {
    00700         return this->m_ptr [total_stride(d.begin())];
    00701     }
    00702
    00703     next_type begin () const
    00704     {
    00705         return *this;
    00706     }
    00707
    00708     next_type end () const
    00709     {
    00710         next_type ret = *this;
    00711         ret += m_shape [level-1];
    00712         return ret;
    00713     }
    00714
    00715     iterator iteratorForDimension(unsigned int d) const
    00716     {
    00717         vigra_precondition(d <= level,
    00718             "MultiIterator<N>::iteratorForDimension(d): d < N required");
    00719         return iterator(this->m_ptr, &m_stride [d], 0);
    00720     }
    00721
    00722     template <unsigned int K>
    00723     MultiIterator<K+1, T, REFERENCE, POINTER> &
    00724     dim()
    00725     {
    00726         return *this;
    00727     }
    00728
    00729     MultiIterator<1, T, REFERENCE, POINTER> &
    00730     dim0() { return *this; }
    00731     MultiIterator<2, T, REFERENCE, POINTER> &
    00732     dim1() { return *this; }
    00733
    00734   protected:
    00735
    00736     difference_type
    00737     total_stride(typename multi_difference_type::const_iterator d) const
    00738     {
    00739         return d[level]*m_stride[level] + base_type::total_stride(d);
    00740     }
    00741 };
    00742
    00743 /********************************************************/
    00744 /*                                                      */
    00745 /*                   MultiIterator<N>                   */
    00746 /*                                                      */
    00747 /********************************************************/
    00748
    00749 /** \brief A multi-dimensional hierarchical iterator to be used with
    00750            \ref vigra::MultiArrayView if it is not strided.
    00751
    00752      See \ref MultiIteratorPage for further documentation.
    00753
    00754 <b>\#include</b> <<a href="multi__iterator_8hxx-source.html">vigra/multi_iterator.hxx</a>>
    00755
    00756 Namespace: vigra
    00757 */
    00758 template <unsigned int N, class T, class REFERENCE, class POINTER>
    00759 class MultiIterator
    00760 : public MultiIterator<N-1, T, REFERENCE, POINTER>
    00761 {
    00762 public:
    00763
    00764         /** the type of the parent in the inheritance hierarchy.
    00765          */
    00766     typedef MultiIterator<N-1, T, REFERENCE, POINTER> base_type;
    00767
    00768         /** the iterator's level in the dimension hierarchy
    00769          */
    00770     enum { level = N-1 };
    00771
    00772         /** the iterator's value type
    00773          */
    00774     typedef T value_type;
    00775
    00776         /** reference type (result of operator[])
    00777          */
    00778     typedef REFERENCE reference;
    00779
    00780         /** const reference type (result of operator[] const)
    00781          */
    00782     typedef const value_type &const_reference;
    00783
    00784         /** pointer type
    00785          */
    00786     typedef POINTER pointer;
    00787
    00788         /** const pointer type
    00789          */
    00790     typedef const value_type *const_pointer;
    00791
    00792         /** multi difference type
    00793             (used for offsetting along all axes simultaneously)
    00794          */
    00795     typedef typename MultiArrayShape<N>::type multi_difference_type;
    00796
    00797         /** difference type (used for offsetting)
    00798          */
    00799     typedef MultiArrayIndex difference_type;
    00800
    00801         /** the MultiIterator for the next lower dimension.
    00802          */
    00803     typedef base_type next_type;
    00804
    00805         /** the 1-dimensional iterator for this iterator hierarchy
    00806             (result of iteratorForDimension()).
    00807         */
    00808     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
    00809
    00810         /** the iterator tag (image traverser)
    00811         */
    00812     typedef multi_dimensional_traverser_tag iterator_category;
    00813
    00814     /* use default copy constructor and assignment operator */
    00815
    00816         /** default constructor.
    00817         */
    00818     MultiIterator ()
    00819     {}
    00820
    00821         /** construct from pointer, strides (offset of a sample to the
    00822             next) for every dimension, and the shape.
    00823         */
    00824     MultiIterator (pointer ptr,
    00825                    const difference_type *stride,
    00826                    const difference_type *shape)
    00827         : base_type (ptr, stride, shape)
    00828     {}
    00829
    00830
    00831         /** prefix-increment the iterator in it's current dimension
    00832          */
    00833     void operator++ ()
    00834     {
    00835         this->m_ptr += this->m_stride [level];
    00836     }
    00837
    00838         /** prefix-decrement the iterator in it's current dimension
    00839          */
    00840     void operator-- ()
    00841     {
    00842         this->m_ptr -= this->m_stride [level];
    00843     }
    00844
    00845         /** postfix-increment the iterator in it's current dimension
    00846          */
    00847     MultiIterator operator++ (int)
    00848     {
    00849         MultiIterator ret = *this;
    00850         ++(*this);
    00851         return ret;
    00852     }
    00853
    00854         /** postfix-decrement the iterator in it's current dimension
    00855          */
    00856     MultiIterator operator-- (int)
    00857     {
    00858         MultiIterator ret = *this;
    00859         --(*this);
    00860         return ret;
    00861     }
    00862
    00863         /** increment the iterator in it's current dimension
    00864             by the given value.
    00865         */
    00866     MultiIterator & operator+= (difference_type n)
    00867     {
    00868         this->m_ptr += n * this->m_stride [level];
    00869         return *this;
    00870     }
    00871
    00872         /** increment the iterator in all dimensions
    00873             by the given offset.
    00874         */
    00875     MultiIterator & operator+= (multi_difference_type const & d)
    00876     {
    00877         this->m_ptr += total_stride(d.begin());
    00878         return *this;
    00879     }
    00880
    00881         /** decrement the iterator in it's current dimension
    00882             by the given value.
    00883         */
    00884     MultiIterator & operator-= (difference_type n)
    00885     {
    00886         this->m_ptr -= n * this->m_stride [level];
    00887         return *this;
    00888     }
    00889
    00890         /** decrement the iterator in all dimensions
    00891             by the given offset.
    00892         */
    00893     MultiIterator & operator-= (multi_difference_type const & d)
    00894     {
    00895         this->m_ptr -= total_stride(d.begin());
    00896         return *this;
    00897     }
    00898
    00899         /** addition within current dimension
    00900          */
    00901     MultiIterator operator+ (difference_type n) const
    00902     {
    00903         MultiIterator ret = *this;
    00904         ret += n;
    00905         return ret;
    00906     }
    00907
    00908         /** addition along all dimensions
    00909          */
    00910     MultiIterator operator+ (multi_difference_type const & d) const
    00911     {
    00912         MultiIterator ret = *this;
    00913         ret += d;
    00914         return ret;
    00915     }
    00916
    00917         /** difference of two iterators in the current dimension.
    00918             The result of this operation is undefined if the iterator
    00919             doesn't point to element 0 in all dimensions below its current dimension.
    00920         */
    00921     difference_type operator- (MultiIterator const & d) const
    00922     {
    00923         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
    00924     }
    00925
    00926         /** subtraction within current dimension
    00927          */
    00928     MultiIterator operator- (difference_type n) const
    00929     {
    00930         MultiIterator ret = *this;
    00931         ret -= n;
    00932         return ret;
    00933     }
    00934
    00935         /** subtraction along all dimensions
    00936          */
    00937     MultiIterator operator- (multi_difference_type const & d) const
    00938     {
    00939         MultiIterator ret = *this;
    00940         ret -= d;
    00941         return ret;
    00942     }
    00943
    00944 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
    00945         /** derefenrence item
    00946          */
    00947     reference operator* () const;
    00948
    00949         /** get address of current item
    00950          */
    00951     pointer get () const;
    00952
    00953         /** call method of current item
    00954          */
    00955     pointer operator->() const;
    00956
    00957         /** inequality. True if iterators reference different items.
    00958          */
    00959     bool operator!= (const MultiIterator &rhs) const;
    00960
    00961         /** equality. True if iterators reference the same items.
    00962          */
    00963     bool operator== (const MultiIterator &rhs) const;
    00964
    00965         /** less than.
    00966          */
    00967     bool operator< (const MultiIterator &rhs) const;
    00968
    00969         /** less or equal.
    00970          */
    00971     bool operator<= (const MultiIterator &rhs) const;
    00972
    00973         /** greater than.
    00974          */
    00975     bool operator> (const MultiIterator &rhs) const;
    00976
    00977         /** greater or equal.
    00978          */
    00979     bool operator>= (const MultiIterator &rhs) const;
    00980 #endif
    00981
    00982         /** access the array element at the given offset in
    00983         the current dimension.
    00984         */
    00985     reference operator[] (difference_type n) const
    00986     {
    00987         return this->m_ptr [n* this->m_stride [level]];
    00988     }
    00989
    00990         /** access the array element at the given offset.
    00991         */
    00992     reference operator[] (multi_difference_type const & d) const
    00993     {
    00994         return this->m_ptr [total_stride(d.begin())];
    00995     }
    00996
    00997         /** Return the (N-1)-dimensional multi-iterator that points to
    00998             the first (N-1)-dimensional subarray of the
    00999             N-dimensional array this iterator is referring to.
    01000             The result is only valid if this iterator refers to location
    01001             0 in <em>all</em> dimensions below its current dimension N,
    01002             otherwise it is undefined. Usage:
    01003
    01004             \code
    01005
    01006             MultiIterator<2, int> outer = ...;  // this iterator
    01007
    01008             MultiIterator<2, int>::next_type inner = outer.begin();
    01009             for(; inner != outer.end(); ++inner)
    01010             {
    01011                 // manipulate current 1D subimage
    01012             }
    01013             \endcode
    01014         */
    01015     next_type begin () const
    01016     {
    01017         return *this;
    01018     }
    01019
    01020         /** Return the (N-1)-dimensional multi-iterator that points beyond
    01021             the last (N-1)-dimensional subarray of the
    01022             N-dimensional array this iterator is referring to.
    01023             The result is only valid if this iterator refers to location
    01024             0 in <em>all</em> dimensions below its current dimension N,
    01025             otherwise it is undefined.
    01026         */
    01027     next_type end () const
    01028     {
    01029         next_type ret = *this;
    01030         ret += this->m_shape [level-1];
    01031         return ret;
    01032     }
    01033
    01034         /** Get a 1-dimensional, STL-compatible iterator for the
    01035             given dimension, pointing to the current element of <TT>this</TT>.
    01036             Usage:
    01037
    01038             \code
    01039
    01040             MultiIterator<3, int> outer = ...;  // this iterator
    01041
    01042             MultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
    01043             MultiIterator<3, int>::iterator end = i + height;
    01044             for(; i != end; ++i)
    01045             {
    01046                 // go down the current column starting at the location of 'outer'
    01047             }
    01048             \endcode
    01049         */
    01050     iterator iteratorForDimension(unsigned int d) const
    01051     {
    01052         vigra_precondition(d <= level,
    01053             "MultiIterator<N>::iteratorForDimension(d): d < N required");
    01054         return iterator(this->m_ptr, &this->m_stride [d], 0);
    01055     }
    01056         /** Return the multi-iterator that operates on dimension K in order
    01057             to manipulate this dimension directly. Usage:
    01058
    01059             \code
    01060
    01061             MultiIterator<3, int> i3 = ...;
    01062
    01063             i3.template dim<2>()++;  // increment outer dimension
    01064             i3.template dim<0>()++;  // increment inner dimension
    01065             \endcode
    01066
    01067             For convenience, the same functionality is also available
    01068             as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
    01069
    01070             \code
    01071
    01072             MultiIterator<3, int> i3 = ...;
    01073
    01074             i3.dim2()++;  // increment outer dimension
    01075             i3.dim0()++;  // increment inner dimension
    01076             \endcode
    01077         */
    01078     template <unsigned int K>
    01079     MultiIterator<K+1, T, REFERENCE, POINTER> &
    01080     dim()
    01081     {
    01082         return *this;
    01083     }
    01084
    01085     MultiIterator<1, T, REFERENCE, POINTER> &
    01086     dim0() { return *this; }
    01087     MultiIterator<2, T, REFERENCE, POINTER> &
    01088     dim1() { return *this; }
    01089     MultiIterator<3, T, REFERENCE, POINTER> &
    01090     dim2() { return *this; }
    01091     MultiIterator<4, T, REFERENCE, POINTER> &
    01092     dim3() { return *this; }
    01093     MultiIterator<5, T, REFERENCE, POINTER> &
    01094     dim4() { return *this; }
    01095
    01096   protected:
    01097
    01098     difference_type
    01099     total_stride(typename multi_difference_type::const_iterator d) const
    01100     {
    01101         return d[level]*this->m_stride[level] + base_type::total_stride(d);
    01102     }
    01103
    01104 };
    01105
    01106 /********************************************************/
    01107 /*                                                      */
    01108 /*                      StridedMultiIterator            */
    01109 /*                                                      */
    01110 /********************************************************/
    01111
    01112 template <unsigned int N, class T, class REFERENCE, class POINTER>
    01113 class StridedMultiIterator;
    01114
    01115 /********************************************************/
    01116 /*                                                      */
    01117 /*                   StridedMultiIterator<1>            */
    01118 /*                                                      */
    01119 /********************************************************/
    01120
    01121 //
    01122 template <class T, class REFERENCE, class POINTER>
    01123 class StridedMultiIterator<1, T, REFERENCE, POINTER>
    01124 {
    01125   public:
    01126     enum { level = 0 };
    01127     typedef T value_type;
    01128     typedef REFERENCE reference;
    01129     typedef const value_type &const_reference;
    01130     typedef POINTER pointer;
    01131     typedef const value_type *const_pointer;
    01132     typedef typename MultiArrayShape<1>::type multi_difference_type;
    01133     typedef MultiArrayIndex difference_type;
    01134     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
    01135     typedef std::random_access_iterator_tag iterator_category;
    01136
    01137   protected:
    01138     pointer m_ptr;
    01139     difference_type m_stride;
    01140
    01141     /* use default copy constructor and assignment operator */
    01142
    01143   public:
    01144     StridedMultiIterator ()
    01145         : m_ptr (0), m_stride (0)
    01146     {}
    01147
    01148     StridedMultiIterator (pointer ptr,
    01149           const difference_type *stride,
    01150           const difference_type *)
    01151         : m_ptr (ptr), m_stride (stride [level])
    01152     {}
    01153
    01154     void operator++ ()
    01155     {
    01156         m_ptr += m_stride;
    01157     }
    01158
    01159     void operator-- ()
    01160     {
    01161         m_ptr -= m_stride;
    01162     }
    01163
    01164     StridedMultiIterator operator++ (int)
    01165     {
    01166         StridedMultiIterator ret = *this;
    01167         ++(*this);
    01168         return ret;
    01169     }
    01170
    01171     StridedMultiIterator operator-- (int)
    01172     {
    01173         StridedMultiIterator ret = *this;
    01174         --(*this);
    01175         return ret;
    01176     }
    01177
    01178     StridedMultiIterator &operator+= (difference_type n)
    01179     {
    01180         m_ptr += n * m_stride;
    01181         return *this;
    01182     }
    01183
    01184     StridedMultiIterator & operator+= (multi_difference_type const & d)
    01185     {
    01186         m_ptr += d[level] * m_stride;
    01187         return *this;
    01188     }
    01189
    01190     StridedMultiIterator &operator-= (difference_type n)
    01191     {
    01192         m_ptr -= n * m_stride;
    01193         return *this;
    01194     }
    01195
    01196     StridedMultiIterator & operator-= (multi_difference_type const & d)
    01197     {
    01198         m_ptr -= d[level] * m_stride;
    01199         return *this;
    01200     }
    01201
    01202     StridedMultiIterator operator+ (difference_type n) const
    01203     {
    01204         StridedMultiIterator ret = *this;
    01205         ret += n;
    01206         return ret;
    01207     }
    01208
    01209     StridedMultiIterator operator+ (multi_difference_type const & d) const
    01210     {
    01211         StridedMultiIterator ret = *this;
    01212         ret += d;
    01213         return ret;
    01214     }
    01215
    01216     difference_type operator- (StridedMultiIterator const & d) const
    01217     {
    01218         return (m_ptr - d.m_ptr) / m_stride;
    01219     }
    01220
    01221     StridedMultiIterator operator- (difference_type n) const
    01222     {
    01223         StridedMultiIterator ret = *this;
    01224         ret -= n;
    01225         return ret;
    01226     }
    01227
    01228     StridedMultiIterator operator- (multi_difference_type const & d) const
    01229     {
    01230         StridedMultiIterator ret = *this;
    01231         ret -= d;
    01232         return ret;
    01233     }
    01234
    01235     reference operator[] (difference_type n) const
    01236     {
    01237         return m_ptr [n*m_stride];
    01238     }
    01239
    01240     reference operator[] (multi_difference_type const & d) const
    01241     {
    01242         return m_ptr [d[level]*m_stride];
    01243     }
    01244
    01245     reference operator* () const
    01246     {
    01247         return *m_ptr;
    01248     }
    01249
    01250     pointer get () const
    01251     {
    01252         return m_ptr;
    01253     }
    01254
    01255     pointer operator->() const
    01256     {
    01257         return &(operator*());
    01258     }
    01259
    01260     bool operator!= (const StridedMultiIterator &rhs) const
    01261     {
    01262         return m_ptr != rhs.m_ptr;
    01263     }
    01264
    01265     bool operator== (const StridedMultiIterator &rhs) const
    01266     {
    01267         return m_ptr == rhs.m_ptr;
    01268     }
    01269
    01270     bool operator< (const StridedMultiIterator &rhs) const
    01271     {
    01272         return m_ptr < rhs.m_ptr;
    01273     }
    01274
    01275     bool operator<= (const StridedMultiIterator &rhs) const
    01276     {
    01277         return m_ptr <= rhs.m_ptr;
    01278     }
    01279
    01280     bool operator> (const StridedMultiIterator &rhs) const
    01281     {
    01282         return m_ptr > rhs.m_ptr;
    01283     }
    01284
    01285     bool operator>= (const StridedMultiIterator &rhs) const
    01286     {
    01287         return m_ptr >= rhs.m_ptr;
    01288     }
    01289
    01290     iterator iteratorForDimension(unsigned int d) const
    01291     {
    01292         vigra_precondition(d == 0,
    01293             "StridedMultiIterator<1>::iteratorForDimension(d): d == 0 required");
    01294         const difference_type stride = 1;
    01295         return iterator(m_ptr, &stride, 0);
    01296     }
    01297
    01298     template <unsigned int K>
    01299     StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
    01300     dim()
    01301     {
    01302         return *this;
    01303     }
    01304
    01305     StridedMultiIterator<1, T, REFERENCE, POINTER> &
    01306     dim0() { return *this; }
    01307
    01308   protected:
    01309
    01310     difference_type
    01311     total_stride(typename multi_difference_type::const_iterator d) const
    01312     {
    01313         return d[level] * m_stride;
    01314     }
    01315 };
    01316
    01317 /********************************************************/
    01318 /*                                                      */
    01319 /*                   StridedMultiIterator<2>            */
    01320 /*                                                      */
    01321 /********************************************************/
    01322
    01323 //
    01324 template <class T, class REFERENCE, class POINTER>
    01325 class StridedMultiIterator<2, T, REFERENCE, POINTER>
    01326 : public StridedMultiIterator<1, T, REFERENCE, POINTER>
    01327 {
    01328   public:
    01329
    01330     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
    01331     enum { level = 1 };
    01332     typedef T value_type;
    01333     typedef REFERENCE reference;
    01334     typedef const value_type &const_reference;
    01335     typedef POINTER pointer;
    01336     typedef const value_type *const_pointer;
    01337     typedef typename MultiArrayShape<2>::type multi_difference_type;
    01338     typedef MultiArrayIndex difference_type;
    01339     typedef base_type next_type;
    01340     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
    01341     typedef multi_dimensional_traverser_tag iterator_category;
    01342
    01343   protected:
    01344     const difference_type *m_stride;
    01345     const difference_type *m_shape;
    01346
    01347   public:
    01348     /* use default copy constructor and assignment operator */
    01349
    01350     StridedMultiIterator ()
    01351         : base_type (),
    01352           m_stride (0), m_shape (0)
    01353     {}
    01354
    01355     StridedMultiIterator (pointer ptr,
    01356           const difference_type *stride,
    01357           const difference_type *shape)
    01358         : base_type (ptr, stride, shape),
    01359           m_stride (stride), m_shape (shape)
    01360     {}
    01361
    01362     void operator++ ()
    01363     {
    01364         this->m_ptr += m_stride [level];
    01365     }
    01366
    01367     void operator-- ()
    01368     {
    01369         this->m_ptr -= m_stride [level];
    01370     }
    01371
    01372     StridedMultiIterator operator++ (int)
    01373     {
    01374         StridedMultiIterator ret = *this;
    01375         ++(*this);
    01376         return ret;
    01377     }
    01378
    01379     StridedMultiIterator operator-- (int)
    01380     {
    01381         StridedMultiIterator ret = *this;
    01382         --(*this);
    01383         return ret;
    01384     }
    01385
    01386     StridedMultiIterator & operator+= (difference_type n)
    01387     {
    01388         this->m_ptr += n * m_stride [level];
    01389         return *this;
    01390     }
    01391
    01392     StridedMultiIterator & operator+= (multi_difference_type const & d)
    01393     {
    01394         this->m_ptr += total_stride(d.begin());
    01395         return *this;
    01396     }
    01397
    01398     StridedMultiIterator  &operator-= (difference_type n)
    01399     {
    01400         this->m_ptr -= n * m_stride [level];
    01401         return *this;
    01402     }
    01403
    01404     StridedMultiIterator & operator-= (multi_difference_type const & d)
    01405     {
    01406         this->m_ptr -= total_stride(d.begin());
    01407         return *this;
    01408     }
    01409
    01410     StridedMultiIterator operator+ (difference_type n) const
    01411     {
    01412         StridedMultiIterator ret = *this;
    01413         ret += n;
    01414         return ret;
    01415     }
    01416
    01417     StridedMultiIterator operator+ (multi_difference_type const & d) const
    01418     {
    01419         StridedMultiIterator ret = *this;
    01420         ret += d;
    01421         return ret;
    01422     }
    01423
    01424     difference_type operator- (StridedMultiIterator const & d) const
    01425     {
    01426         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
    01427     }
    01428
    01429     StridedMultiIterator operator- (difference_type n) const
    01430     {
    01431         StridedMultiIterator ret = *this;
    01432         ret -= n;
    01433         return ret;
    01434     }
    01435
    01436     StridedMultiIterator operator- (multi_difference_type const & d) const
    01437     {
    01438         StridedMultiIterator ret = *this;
    01439         ret -= d;
    01440         return ret;
    01441     }
    01442
    01443     reference operator[] (difference_type n) const
    01444     {
    01445         return this->m_ptr [n*m_stride [level]];
    01446     }
    01447
    01448     reference operator[] (multi_difference_type const & d) const
    01449     {
    01450         return this->m_ptr [total_stride(d.begin())];
    01451     }
    01452
    01453     next_type begin () const
    01454     {
    01455         return *this;
    01456     }
    01457
    01458     next_type end () const
    01459     {
    01460         next_type ret = *this;
    01461         ret += m_shape [level-1];
    01462         return ret;
    01463     }
    01464
    01465     iterator iteratorForDimension(unsigned int d) const
    01466     {
    01467         vigra_precondition(d <= level,
    01468             "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
    01469         return iterator(this->m_ptr, &m_stride [d], 0);
    01470     }
    01471
    01472     template <unsigned int K>
    01473     StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
    01474     dim()
    01475     {
    01476         return *this;
    01477     }
    01478
    01479     StridedMultiIterator<1, T, REFERENCE, POINTER> &
    01480     dim0() { return *this; }
    01481     StridedMultiIterator<2, T, REFERENCE, POINTER> &
    01482     dim1() { return *this; }
    01483
    01484   protected:
    01485
    01486     difference_type
    01487     total_stride(typename multi_difference_type::const_iterator d) const
    01488     {
    01489         return d[level]*m_stride[level] + base_type::total_stride(d);
    01490     }
    01491 };
    01492
    01493 /********************************************************/
    01494 /*                                                      */
    01495 /*                   StridedMultiIterator<N>            */
    01496 /*                                                      */
    01497 /********************************************************/
    01498
    01499 /** \brief A multi-dimensional hierarchical iterator to be used with
    01500            \ref vigra::MultiArrayView if it is not strided.
    01501
    01502      See \ref MultiIteratorPage for further documentation.
    01503
    01504 <b>\#include</b> <<a href="multi__iterator_8hxx-source.html">vigra/multi_iterator.hxx</a>>
    01505
    01506 Namespace: vigra
    01507 */
    01508 template <unsigned int N, class T, class REFERENCE, class POINTER>
    01509 class StridedMultiIterator
    01510 : public StridedMultiIterator<N-1, T, REFERENCE, POINTER>
    01511 {
    01512 public:
    01513
    01514         /** the type of the parent in the inheritance hierarchy.
    01515          */
    01516     typedef StridedMultiIterator<N-1, T, REFERENCE, POINTER> base_type;
    01517
    01518         /** the iterator's level in the dimension hierarchy
    01519          */
    01520     enum { level = N-1 };
    01521
    01522         /** the iterator's value type
    01523          */
    01524     typedef T value_type;
    01525
    01526         /** reference type (result of operator[])
    01527          */
    01528     typedef REFERENCE reference;
    01529
    01530         /** const reference type (result of operator[] const)
    01531          */
    01532     typedef const value_type &const_reference;
    01533
    01534         /** pointer type
    01535          */
    01536     typedef POINTER pointer;
    01537
    01538         /** const pointer type
    01539          */
    01540     typedef const value_type *const_pointer;
    01541
    01542         /** multi difference type
    01543             (used for offsetting along all axes simultaneously)
    01544          */
    01545     typedef typename MultiArrayShape<N>::type multi_difference_type;
    01546
    01547         /** difference type (used for offsetting)
    01548          */
    01549     typedef MultiArrayIndex difference_type;
    01550
    01551         /** the StridedMultiIterator for the next lower dimension.
    01552          */
    01553     typedef base_type next_type;
    01554
    01555         /** the 1-dimensional iterator for this iterator hierarchy
    01556             (result of iteratorForDimension()).
    01557         */
    01558     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
    01559
    01560         /** the iterator tag (image traverser)
    01561         */
    01562     typedef multi_dimensional_traverser_tag iterator_category;
    01563
    01564     /* use default copy constructor and assignment operator */
    01565
    01566         /** default constructor.
    01567         */
    01568     StridedMultiIterator ()
    01569     {}
    01570
    01571         /** construct from pointer, strides (offset of a sample to the
    01572             next) for every dimension, and the shape.
    01573         */
    01574     StridedMultiIterator (pointer ptr,
    01575                    const difference_type *stride,
    01576                    const difference_type *shape)
    01577         : base_type (ptr, stride, shape)
    01578     {}
    01579
    01580
    01581         /** prefix-increment the iterator in it's current dimension
    01582          */
    01583     void operator++ ()
    01584     {
    01585         this->m_ptr += this->m_stride [level];
    01586     }
    01587
    01588         /** prefix-decrement the iterator in it's current dimension
    01589          */
    01590     void operator-- ()
    01591     {
    01592         this->m_ptr -= this->m_stride [level];
    01593     }
    01594
    01595         /** postfix-increment the iterator in it's current dimension
    01596          */
    01597     StridedMultiIterator operator++ (int)
    01598     {
    01599         StridedMultiIterator ret = *this;
    01600         ++(*this);
    01601         return ret;
    01602     }
    01603
    01604         /** postfix-decrement the iterator in it's current dimension
    01605          */
    01606     StridedMultiIterator operator-- (int)
    01607     {
    01608         StridedMultiIterator ret = *this;
    01609         --(*this);
    01610         return ret;
    01611     }
    01612
    01613         /** increment the iterator in it's current dimension
    01614             by the given value.
    01615         */
    01616     StridedMultiIterator & operator+= (difference_type n)
    01617     {
    01618         this->m_ptr += n * this->m_stride [level];
    01619         return *this;
    01620     }
    01621
    01622         /** increment the iterator in all dimensions
    01623             by the given offset.
    01624         */
    01625     StridedMultiIterator & operator+= (multi_difference_type const & d)
    01626     {
    01627         this->m_ptr += total_stride(d.begin());
    01628         return *this;
    01629     }
    01630
    01631         /** decrement the iterator in it's current dimension
    01632             by the given value.
    01633         */
    01634     StridedMultiIterator & operator-= (difference_type n)
    01635     {
    01636         this->m_ptr -= n * this->m_stride [level];
    01637         return *this;
    01638     }
    01639
    01640         /** decrement the iterator in all dimensions
    01641             by the given offset.
    01642         */
    01643     StridedMultiIterator & operator-= (multi_difference_type const & d)
    01644     {
    01645         this->m_ptr -= total_stride(d.begin());
    01646         return *this;
    01647     }
    01648
    01649         /** addition within current dimension
    01650          */
    01651     StridedMultiIterator operator+ (difference_type n) const
    01652     {
    01653         StridedMultiIterator ret = *this;
    01654         ret += n;
    01655         return ret;
    01656     }
    01657
    01658         /** addition along all dimensions
    01659          */
    01660     StridedMultiIterator operator+ (multi_difference_type const & d) const
    01661     {
    01662         StridedMultiIterator ret = *this;
    01663         ret += d;
    01664         return ret;
    01665     }
    01666
    01667         /** difference of two iterators in the current dimension.
    01668             The result of this operation is undefined if the iterator
    01669             doesn't point to element 0 in all dimensions below its current dimension.
    01670         */
    01671     difference_type operator- (StridedMultiIterator const & d) const
    01672     {
    01673         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
    01674     }
    01675
    01676         /** subtraction within current dimension
    01677          */
    01678     StridedMultiIterator operator- (difference_type n) const
    01679     {
    01680         StridedMultiIterator ret = *this;
    01681         ret -= n;
    01682         return ret;
    01683     }
    01684
    01685         /** subtraction along all dimensions
    01686          */
    01687     StridedMultiIterator operator- (multi_difference_type const & d) const
    01688     {
    01689         StridedMultiIterator ret = *this;
    01690         ret -= d;
    01691         return ret;
    01692     }
    01693
    01694 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
    01695         /** derefenrence item
    01696          */
    01697     reference operator* () const;
    01698
    01699         /** get address of current item
    01700          */
    01701     pointer get () const;
    01702
    01703         /** call method of current item
    01704          */
    01705     pointer operator->() const;
    01706
    01707         /** inequality. True if iterators reference different items.
    01708          */
    01709     bool operator!= (const StridedMultiIterator &rhs) const;
    01710
    01711         /** equality. True if iterators reference the same items.
    01712          */
    01713     bool operator== (const StridedMultiIterator &rhs) const;
    01714
    01715         /** less than.
    01716          */
    01717     bool operator< (const StridedMultiIterator &rhs) const;
    01718
    01719         /** less or equal.
    01720          */
    01721     bool operator<= (const StridedMultiIterator &rhs) const;
    01722
    01723         /** greater than.
    01724          */
    01725     bool operator> (const StridedMultiIterator &rhs) const;
    01726
    01727         /** greater or equal.
    01728          */
    01729     bool operator>= (const StridedMultiIterator &rhs) const;
    01730 #endif
    01731
    01732         /** access the array element at the given offset in
    01733         the current dimension.
    01734         */
    01735     reference operator[] (difference_type n) const
    01736     {
    01737         return this->m_ptr [n* this->m_stride [level]];
    01738     }
    01739
    01740         /** access the array element at the given offset.
    01741         */
    01742     reference operator[] (multi_difference_type const & d) const
    01743     {
    01744         return this->m_ptr [total_stride(d.begin())];
    01745     }
    01746
    01747         /** Return the (N-1)-dimensional multi-iterator that points to
    01748             the first (N-1)-dimensional subarray of the
    01749             N-dimensional array this iterator is referring to.
    01750             The result is only valid if this iterator refers to location
    01751             0 in <em>all</em> dimensions below its current dimension N,
    01752             otherwise it is undefined. Usage:
    01753
    01754             \code
    01755
    01756             StridedMultiIterator<2, int> outer = ...;  // this iterator
    01757
    01758             StridedMultiIterator<2, int>::next_type inner = outer.begin();
    01759             for(; inner != outer.end(); ++inner)
    01760             {
    01761                 // manipulate current 1D subimage
    01762             }
    01763             \endcode
    01764         */
    01765     next_type begin () const
    01766     {
    01767         return *this;
    01768     }
    01769
    01770         /** Return the (N-1)-dimensional multi-iterator that points beyond
    01771             the last (N-1)-dimensional subarray of the
    01772             N-dimensional array this iterator is referring to.
    01773             The result is only valid if this iterator refers to location
    01774             0 in <em>all</em> dimensions below its current dimension N,
    01775             otherwise it is undefined.
    01776         */
    01777     next_type end () const
    01778     {
    01779         next_type ret = *this;
    01780         ret += this->m_shape [level-1];
    01781         return ret;
    01782     }
    01783
    01784         /** Get a 1-dimensional, STL-compatible iterator for the
    01785             given dimension, pointing to the current element of <TT>this</TT>.
    01786             Usage:
    01787
    01788             \code
    01789
    01790             StridedMultiIterator<3, int> outer = ...;  // this iterator
    01791
    01792             StridedMultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
    01793             StridedMultiIterator<3, int>::iterator end = i + height;
    01794             for(; i != end; ++i)
    01795             {
    01796                 // go down the current column starting at the location of 'outer'
    01797             }
    01798             \endcode
    01799         */
    01800     iterator iteratorForDimension(unsigned int d) const
    01801     {
    01802         vigra_precondition(d <= level,
    01803             "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
    01804         return iterator(this->m_ptr, &this->m_stride [d], 0);
    01805     }
    01806         /** Return the multi-iterator that operates on dimension K in order
    01807             to manipulate this dimension directly. Usage:
    01808
    01809             \code
    01810
    01811             StridedMultiIterator<3, int> i3 = ...;
    01812
    01813             i3.template dim<2>()++;  // increment outer dimension
    01814             i3.template dim<0>()++;  // increment inner dimension
    01815             \endcode
    01816
    01817             For convenience, the same functionality is also available
    01818             as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
    01819
    01820             \code
    01821
    01822             StridedMultiIterator<3, int> i3 = ...;
    01823
    01824             i3.dim2()++;  // increment outer dimension
    01825             i3.dim0()++;  // increment inner dimension
    01826             \endcode
    01827         */
    01828     template <unsigned int K>
    01829     StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
    01830     dim()
    01831     {
    01832         return *this;
    01833     }
    01834
    01835     StridedMultiIterator<1, T, REFERENCE, POINTER> &
    01836     dim0() { return *this; }
    01837     StridedMultiIterator<2, T, REFERENCE, POINTER> &
    01838     dim1() { return *this; }
    01839     StridedMultiIterator<3, T, REFERENCE, POINTER> &
    01840     dim2() { return *this; }
    01841     StridedMultiIterator<4, T, REFERENCE, POINTER> &
    01842     dim3() { return *this; }
    01843     StridedMultiIterator<5, T, REFERENCE, POINTER> &
    01844     dim4() { return *this; }
    01845
    01846   protected:
    01847
    01848     difference_type
    01849     total_stride(typename multi_difference_type::const_iterator d) const
    01850     {
    01851         return d[level]*this->m_stride[level] + base_type::total_stride(d);
    01852     }
    01853
    01854 };
    01855
    01856 //@}
    01857
    01858 } // namespace vigra
    01859
    01860 #endif // VIGRA_MULTI_ITERATOR_HXX

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