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

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.0 (Thu Aug 25 2011)