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