[ 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)