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

vigra/multi_iterator.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*     Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe       */
00004 /*                                                                      */
00005 /*    This file is part of the VIGRA computer vision library.           */
00006 /*    ( Version 1.3.0, Sep 10 2004 )                                    */
00007 /*    The VIGRA Website is                                              */
00008 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
00009 /*    Please direct questions, bug reports, and contributions to        */
00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00011 /*        vigra@informatik.uni-hamburg.de                               */
00012 /*                                                                      */
00013 /*    Permission is hereby granted, free of charge, to any person       */
00014 /*    obtaining a copy of this software and associated documentation    */
00015 /*    files (the "Software"), to deal in the Software without           */
00016 /*    restriction, including without limitation the rights to use,      */
00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00018 /*    sell copies of the Software, and to permit persons to whom the    */
00019 /*    Software is furnished to do so, subject to the following          */
00020 /*    conditions:                                                       */
00021 /*                                                                      */
00022 /*    The above copyright notice and this permission notice shall be    */
00023 /*    included in all copies or substantial portions of the             */
00024 /*    Software.                                                         */
00025 /*                                                                      */
00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00034 /*                                                                      */
00035 /************************************************************************/
00036 
00037 
00038 #ifndef VIGRA_MULTI_ITERATOR_HXX
00039 #define VIGRA_MULTI_ITERATOR_HXX
00040 
00041 #include <sys/types.h>
00042 #include "tinyvector.hxx"
00043 #include "iteratortags.hxx"
00044 
00045 namespace vigra {
00046 
00047 
00048 template <unsigned int N, class T, 
00049           class REFERENCE = T &, class POINTER = T *> class MultiIterator;
00050 template <unsigned int N, class T, 
00051           class REFERENCE = T &, class POINTER = T *> class StridedMultiIterator;
00052 
00053 /** \page MultiIteratorPage  Multi-dimensional Array Iterators
00054 
00055     General iterators for arrays of arbitrary dimension.
00056 
00057 
00058 <p>
00059 <UL style="list-style-image:url(documents/bullet.gif)">
00060 <LI> \ref vigra::MultiArrayShape
00061      <BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayView or \ref vigra::MultiIterator</em>
00062 <LI> \ref vigra::MultiIterator
00063      <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArrayView</em>
00064 <LI> \ref vigra::StridedMultiIterator
00065      <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayView</em>
00066 <LI> \ref vigra::StridedScanOrderIterator
00067      <BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \ref vigra::MultiArrayView</em>
00068 </UL>
00069 </p>
00070 
00071 <p>
00072     The Multidimensional Iterator concept allows navigation on arrays
00073     of arbitrary dimension. It provides two modes of iteration: 
00074     <em>direct traversal</em>, and <em>hierarchical traversal</em>.
00075     In general, hierarchical traversal will be faster, while only 
00076     direct traversal allows for true random access in all dimensions.
00077     Via the <tt>dim<K>()</tt> function, operations applying to a particular
00078     dimension can be used in the direct traversal mode. In contrast,
00079     direct traversal functions should not be used in the hierarchical mode
00080     because the hierarchical functions are only well-defined if the
00081     iterator points to element 0 in all dimensions below its current dimension.
00082     The current dimension of a <tt>MultiIterator<N, ...></tt> is <tt>N-1</tt>.
00083 </p>
00084 <h3>General Requirements for MultiIterator</h3>
00085 <p>
00086 <table border=2 cellspacing=0 cellpadding=2 width="100%">
00087 <tr><th colspan=2>
00088     Local Types
00089     </th><th>
00090     Meaning
00091     </th>
00092 </tr>
00093 <tr><td colspan=2>
00094     <tt>MultiIterator::value_type</tt></td><td>the underlying arrays's pixel type</td>
00095 </tr>
00096 <tr><td colspan=2>
00097     <tt>MultiIterator::reference</tt></td>
00098     <td>the iterator's reference type (return type of <TT>*iter</TT>). Will be
00099     <tt>value_type &</tt> for a mutable iterator, and convertible to
00100     <tt>value_type const &</tt> for a const iterator.</td>
00101 </tr>
00102 <tr><td colspan=2>
00103     <tt>MultiIterator::pointer</tt></td>
00104     <td>the iterator's pointer type (return type of <TT>iter.operator->()</TT>). Will be
00105     <tt>value_type *</tt> for a mutable iterator, and convertible to
00106     <tt>value_type const *</tt> for a const iterator.</td>
00107 </tr>
00108 <tr><td colspan=2>
00109     <tt>MultiIterator::iterator_category</tt></td>
00110     <td>the iterator tag (<tt>vigra::multi_dimensional_traverser_tag</tt>)</td>
00111 </tr>
00112 <tr><th>
00113     Operation
00114     </th><th>
00115     Result
00116     </th><th>
00117     Semantics
00118     </th>
00119 </tr>
00120 <tr><td colspan=2>
00121     <tt>MultiIterator k;</tt></td><td>default constructor</td>
00122 </tr>
00123 <tr><td colspan=2>
00124     <tt>MultiIterator k(i);</tt></td><td>copy constructor</td>
00125 </tr>
00126 <tr>
00127     <td><tt>k = i</tt></td>
00128     <td><tt>MultiIterator &</tt></td><td>assignment</td>
00129 </tr>
00130 <tr>
00131     <td><tt>i == j</tt></td><td><tt>bool</tt></td>
00132     <td>equality (iterators point to the same element)</td>
00133 </tr>
00134 <tr>
00135     <td><tt>i != j</tt></td><td><tt>bool</tt></td>
00136     <td>inequality (iterators don't point to the same element)</td>
00137 </tr>
00138 <tr>
00139     <td><tt>*i</tt></td><td><tt>MultiIterator::reference</tt></td>
00140     <td>access the current element</td>
00141 </tr>
00142 <tr>
00143     <td><tt>i->member()</tt></td><td>depends on operation</td>
00144     <td>call member function of underlying pixel type via <tt>operator-></tt> of iterator</td>
00145 </tr>
00146 </table>
00147 </p>
00148 <h3>Requirements for Direct Traversal</h3>
00149 <p>
00150 <table border=2 cellspacing=0 cellpadding=2 width="100%">
00151 <tr><th colspan=2>
00152     Local Types
00153     </th><th>
00154     Meaning
00155     </th>
00156 </tr>
00157 <tr><td colspan=2>
00158     <tt>MultiIterator::multi_difference_type</tt></td>
00159     <td>the iterator's multi-dimensional difference type (<TT>TinyVector<MultiArrayIndex, N></TT>)</td>
00160 </tr>
00161 <tr><th>
00162     Operation
00163     </th><th>
00164     Result
00165     </th><th>
00166     Semantics
00167     </th>
00168 </tr>
00169 <tr>
00170     <td><tt>i += diff</tt></td><td><tt>MultiIterator &</tt></td>
00171     <td>add offset to current position</td>
00172 </tr>
00173 <tr>
00174     <td><tt>i -= diff</tt></td><td><tt>MultiIterator &</tt></td>
00175     <td>subtract offset from current position</td>
00176 </tr>
00177 <tr>
00178     <td><tt>i + diff</tt></td><td><tt>MultiIterator</tt></td>
00179     <td>create traverser by adding offset</td>
00180 </tr>
00181 <tr>
00182     <td><tt>i - diff</tt></td><td><tt>MultiIterator</tt></td>
00183     <td>create traverser by subtracting offset</td>
00184 </tr>
00185 <tr>
00186     <td><tt>i[diff]</tt></td><td><tt>MultiIterator::reference</tt></td>
00187     <td>access element at offset <tt>diff</tt></td>
00188 </tr>
00189 <tr>
00190     <td><tt>i.dim<K>()</tt></td><td><tt>MultiIterator<K+1, T, ...></tt></td>
00191     <td>Access the traverser with the current dimension set to K. Typically used to call
00192         navigation functions referring to a particular dimension.<br>
00193         Example (assuming <tt>i, j</tt> are 3-dimensional):<br>
00194         \code
00195         i.dim<0>()++;   // increment dimension 0 
00196         i.dim<1>()++;   // increment dimension 1 
00197         i.dim<2>()++;   // increment dimension 2 
00198         
00199         j += MultiIterator::multi_difference_type(1,1,1);    // same effect
00200         \endcode
00201     </td>
00202 </tr>
00203 <tr><td colspan=3>
00204        <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
00205        <tt>diff</tt> is of type <tt>MultiIterator::multi_difference_type</tt><br>
00206        <tt>K</tt> is an integer compile-time constant
00207     </td>
00208 </tr>
00209 </table>
00210 </p>
00211 <p>
00212 Note that it is impossible to support an <tt>operator-</tt> between two iterators which returns
00213 a <tt>MultiIterator::multi_difference_type</tt> because it is impossible to decide to which
00214 dimension a difference applies. Consider for example, a 2-dimensional iterator <tt>i</tt>, and
00215 let <tt>j = i + multi_difference_type(width, 0)</tt>, <tt>k = i + multi_difference_type(0,1)</tt>, 
00216 where <tt>width</tt> is the array's total width. In general, <tt>j</tt> and <tt>k</tt> point to 
00217 the same memory location, so that the two cases cannot easily be distinguished (it is possible,
00218 but iterator performance will suffer significantly, as is experienced with 
00219 \ref vigra::ImageIterator where differencing is allowed).
00220 </p>
00221 
00222 <h3>Requirements for Hierarchical Traversal</h3>
00223 <p>
00224 <table border=2 cellspacing=0 cellpadding=2 width="100%">
00225 <tr><th colspan=2>
00226     Local Types
00227     </th><th>
00228     Meaning
00229     </th>
00230 </tr>
00231 <tr><td colspan=2>
00232     <tt>MultiIterator::difference_type</tt></td>
00233     <td>the iterator's difference type (<TT>MultiArrayIndex</TT>)</td>
00234 </tr>
00235 <tr><td colspan=2>
00236     <tt>MultiIterator::next_type</tt></td><td>type of the next iterator
00237        (referring to the next lower dimension) in the hierarchy</td>
00238 </tr>
00239 <tr><th>
00240     Operation
00241     </th><th>
00242     Result
00243     </th><th>
00244     Semantics
00245     </th>
00246 </tr>
00247 <tr>
00248     <td><tt>++i</tt></td><td><tt>MultiIterator &</tt></td>
00249     <td>pre-increment iterator in its current dimension</td>
00250 </tr>
00251 <tr>
00252     <td><tt>i++</tt></td><td><tt>MultiIterator</tt></td>
00253     <td>post-increment iterator in its current dimension</td>
00254 </tr>
00255 <tr>
00256     <td><tt>--i</tt></td><td><tt>MultiIterator &</tt></td>
00257     <td>pre-decrement iterator in its current dimension</td>
00258 </tr>
00259 <tr>
00260     <td><tt>i--</tt></td><td><tt>MultiIterator</tt></td>
00261     <td>post-decrement iterator in its current dimension</td>
00262 </tr>
00263 <tr>
00264     <td><tt>i += d</tt></td><td><tt>MultiIterator &</tt></td>
00265     <td>add <tt>d</tt> in current dimension</td>
00266 </tr>
00267 <tr>
00268     <td><tt>i -= d</tt></td><td><tt>MultiIterator &</tt></td>
00269     <td>subtract <tt>d</tt> in from dimension</td>
00270 </tr>
00271 <tr>
00272     <td><tt>i + d</tt></td><td><tt>MultiIterator</tt></td>
00273     <td>create new iterator by adding <tt>d</tt> in current dimension</td>
00274 </tr>
00275 <tr>
00276     <td><tt>i - d</tt></td><td><tt>MultiIterator</tt></td>
00277     <td>create new iterator by subtracting <tt>d</tt> in current dimension</td>
00278 </tr>
00279 <tr>
00280     <td><tt>i - j</tt></td><td><tt>difference_type</tt></td>
00281     <td>difference of <tt>i</tt> and <tt>j</tt> in the current dimension<br>
00282     <em>Note:</em> The result of this operation is undefined if the iterator
00283     doesn't point to element 0 in all dimensions below its current dimension.</td>
00284 </tr>
00285 <tr>
00286     <td><tt>i < j</tt></td><td><tt>bool</tt></td>
00287     <td><tt>i - j < 0</tt><br>
00288     <em>Note:</em> The result of this operation is undefined if the iterator
00289     doesn't point to element 0 in all dimensions below its current dimension.</td>
00290 </tr>
00291 <tr>
00292     <td><tt>i[d]</tt></td><td><tt>MultiIterator::reference</tt></td>
00293     <td>access element by adding offset <tt>d</tt> in current dimension</td>
00294 </tr>
00295 <tr>
00296     <td><tt>i.begin()</tt></td><td><tt>next_type</tt></td>
00297     <td>create the hierarchical iterator pointing to the first element in the 
00298     next lower dimension.<br>
00299     <em>Note:</em> The result of this operation is undefined if the iterator
00300     doesn't point to element 0 in all dimensions below its current dimension.<br>
00301     Usage:<br>
00302     \code
00303     MultiIterator<3, int> i3 = ..., end3 = ...;
00304     for(; i3 != end3; ++i3)
00305     {
00306         MultiIterator<3, int>::next_type i2 = i3.begin(), end2 = i3.end();
00307         for(; i2 != end2; ++i2)
00308         {
00309             MultiIterator<3, int>::next_type::next_type i1 = i2.begin(), end1 = i2.end();
00310             for(; i1 != end1; ++i1)
00311             {
00312                 ... // do something with the current element
00313             }
00314         }
00315     }
00316     
00317     \endcode
00318     </td>
00319 </tr>
00320 <tr>
00321     <td><tt>i.end()</tt></td><td><tt>next_type</tt></td>
00322     <td>create the hierarchical iterator pointing to the past-the-end location in the 
00323     next lower dimension.<br>
00324     <em>Note:</em> The result of this operation is undefined if the iterator
00325     doesn't point to element 0 in all dimensions below its current dimension.</td>
00326 </tr>
00327 <tr><td colspan=3>
00328        <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
00329        <tt>d</tt> is of type <tt>MultiIterator::difference_type</tt>
00330     </td>
00331 </tr>
00332 </table>
00333 </p>
00334 
00335 */
00336 
00337 /** \addtogroup MultiIteratorGroup  Multi-dimensional Array Iterators
00338 
00339     \brief General iterators for arrays of arbitrary dimension.
00340 */
00341 //@{
00342 
00343     /** Index type for a single dimension of a MultiArrayView or
00344         MultiArray.
00345     */
00346 typedef std::ptrdiff_t MultiArrayIndex;
00347 
00348     /** Traits class for the difference type of all MultiIterator, MultiArrayView, and
00349         MultiArray variants.
00350     */
00351 template <unsigned int N>
00352 class MultiArrayShape
00353 {
00354   public:
00355         /** The difference type of all MultiIterator, MultiArrayView, and
00356             MultiArray variants.
00357         */
00358     typedef TinyVector<MultiArrayIndex, N> type;
00359 };
00360 
00361 typedef MultiArrayShape<1>::type Shape1; ///< shape type for MultiArray<1, T>
00362 typedef MultiArrayShape<2>::type Shape2; ///< shape type for MultiArray<2, T>
00363 typedef MultiArrayShape<3>::type Shape3; ///< shape type for MultiArray<3, T>
00364 typedef MultiArrayShape<4>::type Shape4; ///< shape type for MultiArray<4, T>
00365 typedef MultiArrayShape<5>::type Shape5; ///< shape type for MultiArray<5, T>
00366 
00367 /********************************************************/
00368 /*                                                      */
00369 /*                      MultiIterator                   */
00370 /*                                                      */
00371 /********************************************************/
00372 
00373 template <unsigned int N, class T, class REFERENCE, class POINTER>
00374 class MultiIterator;
00375 
00376 /********************************************************/
00377 /*                                                      */
00378 /*                   MultiIterator<1>                   */
00379 /*                                                      */
00380 /********************************************************/
00381 
00382 //
00383 template <class T, class REFERENCE, class POINTER>
00384 class MultiIterator<1, T, REFERENCE, POINTER>
00385 {
00386   public:
00387     enum { level = 0 };
00388     typedef T value_type;
00389     typedef REFERENCE reference;
00390     typedef const value_type &const_reference;
00391     typedef POINTER pointer;
00392     typedef const value_type *const_pointer;
00393     typedef typename MultiArrayShape<1>::type multi_difference_type;
00394     typedef MultiArrayIndex difference_type;
00395     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
00396     typedef std::random_access_iterator_tag iterator_category;
00397 
00398   protected:
00399     pointer m_ptr;
00400 
00401   public:
00402     MultiIterator ()
00403         : m_ptr (0)
00404     {}
00405 
00406     MultiIterator (pointer ptr,
00407           const difference_type *,
00408           const difference_type *)
00409         : m_ptr (ptr)
00410     {}
00411 
00412     void operator++ ()
00413     {
00414         ++m_ptr;
00415     }
00416 
00417     void operator-- ()
00418     {
00419         --m_ptr;
00420     }
00421 
00422     MultiIterator operator++ (int)
00423     {
00424         MultiIterator ret = *this;
00425         ++(*this);
00426         return ret;
00427     }
00428 
00429     MultiIterator operator-- (int)
00430     {
00431         MultiIterator ret = *this;
00432         --(*this);
00433         return ret;
00434     }
00435 
00436     MultiIterator &operator+= (difference_type n)
00437     {
00438         m_ptr += n;
00439         return *this;
00440     }
00441 
00442     MultiIterator & operator+= (multi_difference_type const & d)
00443     {
00444         m_ptr += d[level];
00445         return *this;
00446     }
00447 
00448     MultiIterator &operator-= (difference_type n)
00449     {
00450         m_ptr -= n;
00451         return *this;
00452     }
00453 
00454     MultiIterator & operator-= (multi_difference_type const & d)
00455     {
00456         m_ptr -= d[level];
00457         return *this;
00458     }
00459 
00460     MultiIterator operator+ (difference_type n) const
00461     {
00462         MultiIterator ret = *this;
00463         ret += n;
00464         return ret;
00465     }
00466 
00467     MultiIterator operator+ (multi_difference_type const & d) const
00468     {
00469         MultiIterator ret = *this;
00470         ret += d;
00471         return ret;
00472     }
00473 
00474     difference_type operator- (MultiIterator const & d) const
00475     {
00476         return (m_ptr - d.m_ptr);
00477     }
00478 
00479     MultiIterator operator- (difference_type n) const
00480     {
00481         MultiIterator ret = *this;
00482         ret -= n;
00483         return ret;
00484     }
00485 
00486     MultiIterator operator- (multi_difference_type const & d) const
00487     {
00488         MultiIterator ret = *this;
00489         ret -= d;
00490         return ret;
00491     }
00492 
00493     reference operator[] (difference_type n) const
00494     {
00495         return m_ptr [n];
00496     }
00497 
00498     reference operator[] (multi_difference_type const & d) const
00499     {
00500         return m_ptr [d[level]];
00501     }
00502 
00503     reference operator* () const
00504     {
00505         return *m_ptr;
00506     }
00507 
00508     pointer get () const
00509     {
00510         return m_ptr;
00511     }
00512 
00513     pointer operator->() const
00514     {
00515         return &(operator*());
00516     }
00517 
00518     bool operator!= (const MultiIterator &rhs) const
00519     {
00520         return m_ptr != rhs.m_ptr;
00521     }
00522 
00523     bool operator== (const MultiIterator &rhs) const
00524     {
00525         return m_ptr == rhs.m_ptr;
00526     }
00527 
00528     bool operator< (const MultiIterator &rhs) const
00529     {
00530         return m_ptr < rhs.m_ptr;
00531     }
00532 
00533     bool operator<= (const MultiIterator &rhs) const
00534     {
00535         return m_ptr <= rhs.m_ptr;
00536     }
00537 
00538     bool operator> (const MultiIterator &rhs) const
00539     {
00540         return m_ptr > rhs.m_ptr;
00541     }
00542 
00543     bool operator>= (const MultiIterator &rhs) const
00544     {
00545         return m_ptr >= rhs.m_ptr;
00546     }
00547 
00548     iterator iteratorForDimension(unsigned int d) const
00549     {
00550         vigra_precondition(d == 0,
00551             "MultiIterator<1>::iteratorForDimension(d): d == 0 required");
00552         const difference_type stride = 1;
00553         return iterator(m_ptr, &stride, 0);
00554     }
00555 
00556     template <unsigned int K>
00557     MultiIterator<K+1, T, REFERENCE, POINTER> &
00558     dim()
00559     {
00560         return *this;
00561     }
00562 
00563     MultiIterator<1, T, REFERENCE, POINTER> &
00564     dim0() { return *this; }
00565 
00566   protected:
00567 
00568     difference_type 
00569     total_stride(typename multi_difference_type::const_iterator d) const
00570     {
00571         return d[level];
00572     }
00573 };
00574 
00575 /********************************************************/
00576 /*                                                      */
00577 /*                   MultiIterator<2>                   */
00578 /*                                                      */
00579 /********************************************************/
00580 
00581 //
00582 template <class T, class REFERENCE, class POINTER>
00583 class MultiIterator<2, T, REFERENCE, POINTER>
00584 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
00585 : public MultiIterator<1, T, REFERENCE, POINTER>
00586 #endif
00587 {
00588   public:
00589 
00590     typedef MultiIterator<1, T, REFERENCE, POINTER> base_type;
00591     enum { level = 1 };
00592     typedef T value_type;
00593     typedef REFERENCE reference;
00594     typedef const value_type &const_reference;
00595     typedef POINTER pointer;
00596     typedef const value_type *const_pointer;
00597     typedef typename MultiArrayShape<2>::type multi_difference_type;
00598     typedef MultiArrayIndex difference_type;
00599     typedef base_type next_type;
00600     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
00601     typedef multi_dimensional_traverser_tag iterator_category;
00602 
00603   protected:
00604     const difference_type *m_stride;
00605     const difference_type *m_shape;
00606 
00607   public:
00608     /* use default copy constructor and assignment operator */
00609 
00610     MultiIterator ()
00611         : base_type (),
00612           m_stride (0), m_shape (0)
00613     {}
00614 
00615     MultiIterator (pointer ptr,
00616           const difference_type *stride,
00617           const difference_type *shape)
00618         : base_type (ptr, stride, shape),
00619           m_stride (stride), m_shape (shape)
00620     {}
00621 
00622     void operator++ ()
00623     {
00624         this->m_ptr += m_stride [level];
00625     }
00626 
00627     void operator-- ()
00628     {
00629         this->m_ptr -= m_stride [level];
00630     }
00631 
00632     MultiIterator operator++ (int)
00633     {
00634         MultiIterator ret = *this;
00635         ++(*this);
00636         return ret;
00637     }
00638 
00639     MultiIterator operator-- (int)
00640     {
00641         MultiIterator ret = *this;
00642         --(*this);
00643         return ret;
00644     }
00645 
00646     MultiIterator & operator+= (difference_type n)
00647     {
00648         this->m_ptr += n * m_stride [level];
00649         return *this;
00650     }
00651 
00652     MultiIterator & operator+= (multi_difference_type const & d)
00653     {
00654         this->m_ptr += total_stride(d.begin());
00655         return *this;
00656     }
00657 
00658     MultiIterator  &operator-= (difference_type n)
00659     {
00660         this->m_ptr -= n * m_stride [level];
00661         return *this;
00662     }
00663 
00664     MultiIterator & operator-= (multi_difference_type const & d)
00665     {
00666         this->m_ptr -= total_stride(d.begin());
00667         return *this;
00668     }
00669 
00670     MultiIterator operator+ (difference_type n) const
00671     {
00672         MultiIterator ret = *this;
00673         ret += n;
00674         return ret;
00675     }
00676 
00677     MultiIterator operator+ (multi_difference_type const & d) const
00678     {
00679         MultiIterator ret = *this;
00680         ret += d;
00681         return ret;
00682     }
00683 
00684     difference_type operator- (MultiIterator const & d) const
00685     {
00686         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
00687     }
00688 
00689     MultiIterator operator- (difference_type n) const
00690     {
00691         MultiIterator ret = *this;
00692         ret -= n;
00693         return ret;
00694     }
00695 
00696     MultiIterator operator- (multi_difference_type const & d) const
00697     {
00698         MultiIterator ret = *this;
00699         ret -= d;
00700         return ret;
00701     }
00702 
00703     reference operator[] (difference_type n) const
00704     {
00705         return this->m_ptr [n*m_stride [level]];
00706     }
00707 
00708     reference operator[] (multi_difference_type const & d) const
00709     {
00710         return this->m_ptr [total_stride(d.begin())];
00711     }
00712 
00713     next_type begin () const
00714     {
00715         return *this;
00716     }
00717 
00718     next_type end () const
00719     {
00720         next_type ret = *this;
00721         ret += m_shape [level-1];
00722         return ret;
00723     }
00724 
00725     iterator iteratorForDimension(unsigned int d) const
00726     {
00727         vigra_precondition(d <= level,
00728             "MultiIterator<N>::iteratorForDimension(d): d < N required");
00729         return iterator(this->m_ptr, &m_stride [d], 0);
00730     }
00731 
00732     template <unsigned int K>
00733     MultiIterator<K+1, T, REFERENCE, POINTER> &
00734     dim()
00735     {
00736         return *this;
00737     }
00738 
00739     MultiIterator<1, T, REFERENCE, POINTER> &
00740     dim0() { return *this; }
00741     MultiIterator<2, T, REFERENCE, POINTER> &
00742     dim1() { return *this; }
00743 
00744   protected:
00745 
00746     difference_type 
00747     total_stride(typename multi_difference_type::const_iterator d) const
00748     {
00749         return d[level]*m_stride[level] + base_type::total_stride(d);
00750     }
00751 };
00752 
00753 /********************************************************/
00754 /*                                                      */
00755 /*                   MultiIterator<N>                   */
00756 /*                                                      */
00757 /********************************************************/
00758 
00759 /** \brief A multi-dimensional hierarchical iterator to be used with 
00760            \ref vigra::MultiArrayView if it is not strided.
00761 
00762      See \ref MultiIteratorPage for further documentation.
00763 
00764 <b>\#include</b> <vigra/multi_iterator.hxx>
00765 
00766 Namespace: vigra
00767 */
00768 template <unsigned int N, class T, class REFERENCE, class POINTER>
00769 class MultiIterator 
00770 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
00771 : public MultiIterator<N-1, T, REFERENCE, POINTER>
00772 #endif
00773 {
00774 public:
00775 
00776         /** the type of the parent in the inheritance hierarchy.
00777          */
00778     typedef MultiIterator<N-1, T, REFERENCE, POINTER> base_type;
00779         
00780         /** the iterator's level in the dimension hierarchy
00781          */
00782     enum { level = N-1 };
00783 
00784         /** the iterator's value type
00785          */
00786     typedef T value_type;
00787 
00788         /** reference type (result of operator[])
00789          */
00790     typedef REFERENCE reference;
00791 
00792         /** const reference type (result of operator[] const)
00793          */
00794     typedef const value_type &const_reference;
00795 
00796         /** pointer type
00797          */
00798     typedef POINTER pointer;
00799 
00800         /** const pointer type
00801          */
00802     typedef const value_type *const_pointer;
00803 
00804         /** multi difference type 
00805             (used for offsetting along all axes simultaneously)
00806          */
00807     typedef typename MultiArrayShape<N>::type multi_difference_type;
00808     
00809         /** difference type (used for offsetting)
00810          */
00811     typedef MultiArrayIndex difference_type;
00812 
00813         /** the MultiIterator for the next lower dimension.
00814          */
00815     typedef base_type next_type;
00816 
00817         /** the 1-dimensional iterator for this iterator hierarchy
00818             (result of iteratorForDimension()).
00819         */
00820     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
00821 
00822         /** the iterator tag (image traverser)
00823         */
00824     typedef multi_dimensional_traverser_tag iterator_category;
00825             
00826     /* use default copy constructor and assignment operator */
00827 
00828         /** default constructor.
00829         */
00830     MultiIterator ()
00831     {}
00832 
00833         /** construct from pointer, strides (offset of a sample to the
00834             next) for every dimension, and the shape.
00835         */
00836     MultiIterator (pointer ptr,
00837                    const difference_type *stride,
00838                    const difference_type *shape)
00839         : base_type (ptr, stride, shape)
00840     {}
00841 
00842 
00843         /** prefix-increment the iterator in it's current dimension
00844          */
00845     void operator++ ()
00846     {
00847         this->m_ptr += this->m_stride [level];
00848     }
00849 
00850         /** prefix-decrement the iterator in it's current dimension
00851          */
00852     void operator-- ()
00853     {
00854         this->m_ptr -= this->m_stride [level];
00855     }
00856 
00857         /** postfix-increment the iterator in it's current dimension
00858          */
00859     MultiIterator operator++ (int)
00860     {
00861         MultiIterator ret = *this;
00862         ++(*this);
00863         return ret;
00864     }
00865 
00866         /** postfix-decrement the iterator in it's current dimension
00867          */
00868     MultiIterator operator-- (int)
00869     {
00870         MultiIterator ret = *this;
00871         --(*this);
00872         return ret;
00873     }
00874 
00875         /** increment the iterator in it's current dimension
00876             by the given value.
00877         */
00878     MultiIterator & operator+= (difference_type n)
00879     {
00880         this->m_ptr += n * this->m_stride [level];
00881         return *this;
00882     }
00883 
00884         /** increment the iterator in all dimensions
00885             by the given offset.
00886         */
00887     MultiIterator & operator+= (multi_difference_type const & d)
00888     {
00889         this->m_ptr += total_stride(d.begin());
00890         return *this;
00891     }
00892 
00893         /** decrement the iterator in it's current dimension
00894             by the given value.
00895         */
00896     MultiIterator & operator-= (difference_type n)
00897     {
00898         this->m_ptr -= n * this->m_stride [level];
00899         return *this;
00900     }
00901 
00902         /** decrement the iterator in all dimensions
00903             by the given offset.
00904         */
00905     MultiIterator & operator-= (multi_difference_type const & d)
00906     {
00907         this->m_ptr -= total_stride(d.begin());
00908         return *this;
00909     }
00910 
00911         /** addition within current dimension
00912          */
00913     MultiIterator operator+ (difference_type n) const
00914     {
00915         MultiIterator ret = *this;
00916         ret += n;
00917         return ret;
00918     }
00919 
00920         /** addition along all dimensions
00921          */
00922     MultiIterator operator+ (multi_difference_type const & d) const
00923     {
00924         MultiIterator ret = *this;
00925         ret += d;
00926         return ret;
00927     }
00928 
00929         /** difference of two iterators in the current dimension.
00930             The result of this operation is undefined if the iterator
00931             doesn't point to element 0 in all dimensions below its current dimension.
00932         */
00933     difference_type operator- (MultiIterator const & d) const
00934     {
00935         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
00936     }
00937 
00938         /** subtraction within current dimension
00939          */
00940     MultiIterator operator- (difference_type n) const
00941     {
00942         MultiIterator ret = *this;
00943         ret -= n;
00944         return ret;
00945     }
00946 
00947         /** subtraction along all dimensions
00948          */
00949     MultiIterator operator- (multi_difference_type const & d) const
00950     {
00951         MultiIterator ret = *this;
00952         ret -= d;
00953         return ret;
00954     }
00955 
00956 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
00957         /** derefenrence item
00958          */
00959     reference operator* () const;
00960 
00961         /** get address of current item
00962          */
00963     pointer get () const;
00964 
00965         /** call method of current item
00966          */
00967     pointer operator->() const;
00968 
00969         /** inequality. True if iterators reference different items.
00970          */
00971     bool operator!= (const MultiIterator &rhs) const;
00972 
00973         /** equality. True if iterators reference the same items.
00974          */
00975     bool operator== (const MultiIterator &rhs) const;
00976 
00977         /** less than.
00978          */
00979     bool operator< (const MultiIterator &rhs) const;
00980 
00981         /** less or equal.
00982          */
00983     bool operator<= (const MultiIterator &rhs) const;
00984 
00985         /** greater than.
00986          */
00987     bool operator> (const MultiIterator &rhs) const;
00988     
00989         /** greater or equal.
00990          */
00991     bool operator>= (const MultiIterator &rhs) const;
00992 #endif
00993 
00994         /** access the array element at the given offset in 
00995         the current dimension.
00996         */
00997     reference operator[] (difference_type n) const
00998     {
00999         return this->m_ptr [n* this->m_stride [level]];
01000     }
01001 
01002         /** access the array element at the given offset.
01003         */
01004     reference operator[] (multi_difference_type const & d) const
01005     {
01006         return this->m_ptr [total_stride(d.begin())];
01007     }
01008 
01009         /** Return the (N-1)-dimensional multi-iterator that points to 
01010             the first (N-1)-dimensional subarray of the 
01011             N-dimensional array this iterator is referring to.
01012             The result is only valid if this iterator refers to location
01013             0 in <em>all</em> dimensions below its current dimension N,
01014             otherwise it is undefined. Usage:
01015 
01016             \code
01017 
01018             MultiIterator<2, int> outer = ...;  // this iterator
01019 
01020             MultiIterator<2, int>::next_type inner = outer.begin();
01021             for(; inner != outer.end(); ++inner)
01022             {
01023                 // manipulate current 1D subimage
01024             }
01025             \endcode
01026         */
01027     next_type begin () const
01028     {
01029         return *this;
01030     }
01031 
01032         /** Return the (N-1)-dimensional multi-iterator that points beyond 
01033             the last (N-1)-dimensional subarray of the 
01034             N-dimensional array this iterator is referring to.
01035             The result is only valid if this iterator refers to location
01036             0 in <em>all</em> dimensions below its current dimension N,
01037             otherwise it is undefined.
01038         */
01039     next_type end () const
01040     {
01041         next_type ret = *this;
01042         ret += this->m_shape [level-1];
01043         return ret;
01044     }
01045 
01046         /** Get a 1-dimensional, STL-compatible iterator for the
01047             given dimension, pointing to the current element of <TT>this</TT>.
01048             Usage:
01049 
01050             \code
01051 
01052             MultiIterator<3, int> outer = ...;  // this iterator
01053 
01054             MultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
01055             MultiIterator<3, int>::iterator end = i + height;
01056             for(; i != end; ++i)
01057             {
01058                 // go down the current column starting at the location of 'outer'
01059             }
01060             \endcode            
01061         */
01062     iterator iteratorForDimension(unsigned int d) const
01063     {
01064         vigra_precondition(d <= level,
01065             "MultiIterator<N>::iteratorForDimension(d): d < N required");
01066         return iterator(this->m_ptr, &this->m_stride [d], 0);
01067     }
01068         /** Return the multi-iterator that operates on dimension K in order
01069             to manipulate this dimension directly. Usage:
01070                
01071             \code
01072                 
01073             MultiIterator<3, int> i3 = ...;
01074                 
01075             i3.template dim<2>()++;  // increment outer dimension
01076             i3.template dim<0>()++;  // increment inner dimension
01077             \endcode
01078             
01079             For convenience, the same functionality is also available
01080             as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
01081             
01082             \code
01083                 
01084             MultiIterator<3, int> i3 = ...;
01085                 
01086             i3.dim2()++;  // increment outer dimension
01087             i3.dim0()++;  // increment inner dimension
01088             \endcode            
01089         */
01090     template <unsigned int K>
01091     MultiIterator<K+1, T, REFERENCE, POINTER> &
01092     dim()
01093     {
01094         return *this;
01095     }
01096 
01097     MultiIterator<1, T, REFERENCE, POINTER> &
01098     dim0() { return *this; }
01099     MultiIterator<2, T, REFERENCE, POINTER> &
01100     dim1() { return *this; }
01101     MultiIterator<3, T, REFERENCE, POINTER> &
01102     dim2() { return *this; }
01103     MultiIterator<4, T, REFERENCE, POINTER> &
01104     dim3() { return *this; }
01105     MultiIterator<5, T, REFERENCE, POINTER> &
01106     dim4() { return *this; }
01107 
01108   protected:
01109 
01110     difference_type 
01111     total_stride(typename multi_difference_type::const_iterator d) const
01112     {
01113         return d[level]*this->m_stride[level] + base_type::total_stride(d);
01114     }
01115 
01116 };
01117 
01118 /********************************************************/
01119 /*                                                      */
01120 /*                      StridedMultiIterator            */
01121 /*                                                      */
01122 /********************************************************/
01123 
01124 template <unsigned int N, class T, class REFERENCE, class POINTER>
01125 class StridedMultiIterator;
01126 
01127 /********************************************************/
01128 /*                                                      */
01129 /*                   StridedMultiIterator<1>            */
01130 /*                                                      */
01131 /********************************************************/
01132 
01133 //
01134 template <class T, class REFERENCE, class POINTER>
01135 class StridedMultiIterator<1, T, REFERENCE, POINTER>
01136 {
01137   public:
01138     enum { level = 0 };
01139     typedef T value_type;
01140     typedef REFERENCE reference;
01141     typedef const value_type &const_reference;
01142     typedef POINTER pointer;
01143     typedef const value_type *const_pointer;
01144     typedef typename MultiArrayShape<1>::type multi_difference_type;
01145     typedef MultiArrayIndex difference_type;
01146     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
01147     typedef std::random_access_iterator_tag iterator_category;
01148 
01149   protected:
01150     pointer m_ptr;
01151     difference_type m_stride;
01152 
01153     /* use default copy constructor and assignment operator */
01154 
01155   public:
01156     StridedMultiIterator ()
01157         : m_ptr (0), m_stride (0)
01158     {}
01159 
01160     StridedMultiIterator (pointer ptr,
01161           const difference_type *stride,
01162           const difference_type *)
01163         : m_ptr (ptr), m_stride (stride [level])
01164     {}
01165 
01166     void operator++ ()
01167     {
01168         m_ptr += m_stride;
01169     }
01170 
01171     void operator-- ()
01172     {
01173         m_ptr -= m_stride;
01174     }
01175 
01176     StridedMultiIterator operator++ (int)
01177     {
01178         StridedMultiIterator ret = *this;
01179         ++(*this);
01180         return ret;
01181     }
01182 
01183     StridedMultiIterator operator-- (int)
01184     {
01185         StridedMultiIterator ret = *this;
01186         --(*this);
01187         return ret;
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)
01203     {
01204         m_ptr -= n * m_stride;
01205         return *this;
01206     }
01207 
01208     StridedMultiIterator & operator-= (multi_difference_type const & d)
01209     {
01210         m_ptr -= d[level] * m_stride;
01211         return *this;
01212     }
01213 
01214     StridedMultiIterator operator+ (difference_type n) const
01215     {
01216         StridedMultiIterator ret = *this;
01217         ret += n;
01218         return ret;
01219     }
01220 
01221     StridedMultiIterator operator+ (multi_difference_type const & d) const
01222     {
01223         StridedMultiIterator ret = *this;
01224         ret += d;
01225         return ret;
01226     }
01227 
01228     difference_type operator- (StridedMultiIterator const & d) const
01229     {
01230         return (m_ptr - d.m_ptr) / m_stride;
01231     }
01232 
01233     StridedMultiIterator operator- (difference_type n) const
01234     {
01235         StridedMultiIterator ret = *this;
01236         ret -= n;
01237         return ret;
01238     }
01239 
01240     StridedMultiIterator operator- (multi_difference_type const & d) const
01241     {
01242         StridedMultiIterator ret = *this;
01243         ret -= d;
01244         return ret;
01245     }
01246 
01247     reference operator[] (difference_type n) const
01248     {
01249         return m_ptr [n*m_stride];
01250     }
01251 
01252     reference operator[] (multi_difference_type const & d) const
01253     {
01254         return m_ptr [d[level]*m_stride];
01255     }
01256 
01257     reference operator* () const
01258     {
01259         return *m_ptr;
01260     }
01261 
01262     pointer get () const
01263     {
01264         return m_ptr;
01265     }
01266 
01267     pointer operator->() const
01268     {
01269         return &(operator*());
01270     }
01271 
01272     bool operator!= (const StridedMultiIterator &rhs) const
01273     {
01274         return m_ptr != rhs.m_ptr;
01275     }
01276 
01277     bool operator== (const StridedMultiIterator &rhs) const
01278     {
01279         return m_ptr == rhs.m_ptr;
01280     }
01281 
01282     bool operator< (const StridedMultiIterator &rhs) const
01283     {
01284         return m_ptr < rhs.m_ptr;
01285     }
01286 
01287     bool operator<= (const StridedMultiIterator &rhs) const
01288     {
01289         return m_ptr <= rhs.m_ptr;
01290     }
01291 
01292     bool operator> (const StridedMultiIterator &rhs) const
01293     {
01294         return m_ptr > rhs.m_ptr;
01295     }
01296 
01297     bool operator>= (const StridedMultiIterator &rhs) const
01298     {
01299         return m_ptr >= rhs.m_ptr;
01300     }
01301 
01302     iterator iteratorForDimension(unsigned int d) const
01303     {
01304         vigra_precondition(d == 0,
01305             "StridedMultiIterator<1>::iteratorForDimension(d): d == 0 required");
01306         const difference_type stride = 1;
01307         return iterator(m_ptr, &stride, 0);
01308     }
01309 
01310     template <unsigned int K>
01311     StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
01312     dim()
01313     {
01314         return *this;
01315     }
01316 
01317     StridedMultiIterator<1, T, REFERENCE, POINTER> &
01318     dim0() { return *this; }
01319 
01320   protected:
01321 
01322     difference_type 
01323     total_stride(typename multi_difference_type::const_iterator d) const
01324     {
01325         return d[level] * m_stride;
01326     }
01327 };
01328 
01329 /********************************************************/
01330 /*                                                      */
01331 /*                   StridedMultiIterator<2>            */
01332 /*                                                      */
01333 /********************************************************/
01334 
01335 //
01336 template <class T, class REFERENCE, class POINTER>
01337 class StridedMultiIterator<2, T, REFERENCE, POINTER>
01338 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
01339 : public StridedMultiIterator<1, T, REFERENCE, POINTER>
01340 #endif
01341 {
01342   public:
01343 
01344     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
01345     enum { level = 1 };
01346     typedef T value_type;
01347     typedef REFERENCE reference;
01348     typedef const value_type &const_reference;
01349     typedef POINTER pointer;
01350     typedef const value_type *const_pointer;
01351     typedef typename MultiArrayShape<2>::type multi_difference_type;
01352     typedef MultiArrayIndex difference_type;
01353     typedef base_type next_type;
01354     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
01355     typedef multi_dimensional_traverser_tag iterator_category;
01356 
01357   protected:
01358     const difference_type *m_stride;
01359     const difference_type *m_shape;
01360 
01361   public:
01362     /* use default copy constructor and assignment operator */
01363 
01364     StridedMultiIterator ()
01365         : base_type (),
01366           m_stride (0), m_shape (0)
01367     {}
01368 
01369     StridedMultiIterator (pointer ptr,
01370           const difference_type *stride,
01371           const difference_type *shape)
01372         : base_type (ptr, stride, shape),
01373           m_stride (stride), m_shape (shape)
01374     {}
01375 
01376     void operator++ ()
01377     {
01378         this->m_ptr += m_stride [level];
01379     }
01380 
01381     void operator-- ()
01382     {
01383         this->m_ptr -= m_stride [level];
01384     }
01385 
01386     StridedMultiIterator operator++ (int)
01387     {
01388         StridedMultiIterator ret = *this;
01389         ++(*this);
01390         return ret;
01391     }
01392 
01393     StridedMultiIterator operator-- (int)
01394     {
01395         StridedMultiIterator ret = *this;
01396         --(*this);
01397         return ret;
01398     }
01399 
01400     StridedMultiIterator & operator+= (difference_type n)
01401     {
01402         this->m_ptr += n * m_stride [level];
01403         return *this;
01404     }
01405 
01406     StridedMultiIterator & operator+= (multi_difference_type const & d)
01407     {
01408         this->m_ptr += total_stride(d.begin());
01409         return *this;
01410     }
01411 
01412     StridedMultiIterator  &operator-= (difference_type n)
01413     {
01414         this->m_ptr -= n * m_stride [level];
01415         return *this;
01416     }
01417 
01418     StridedMultiIterator & operator-= (multi_difference_type const & d)
01419     {
01420         this->m_ptr -= total_stride(d.begin());
01421         return *this;
01422     }
01423 
01424     StridedMultiIterator operator+ (difference_type n) const
01425     {
01426         StridedMultiIterator ret = *this;
01427         ret += n;
01428         return ret;
01429     }
01430 
01431     StridedMultiIterator operator+ (multi_difference_type const & d) const
01432     {
01433         StridedMultiIterator ret = *this;
01434         ret += d;
01435         return ret;
01436     }
01437 
01438     difference_type operator- (StridedMultiIterator const & d) const
01439     {
01440         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
01441     }
01442 
01443     StridedMultiIterator operator- (difference_type n) const
01444     {
01445         StridedMultiIterator ret = *this;
01446         ret -= n;
01447         return ret;
01448     }
01449 
01450     StridedMultiIterator operator- (multi_difference_type const & d) const
01451     {
01452         StridedMultiIterator ret = *this;
01453         ret -= d;
01454         return ret;
01455     }
01456 
01457     reference operator[] (difference_type n) const
01458     {
01459         return this->m_ptr [n*m_stride [level]];
01460     }
01461 
01462     reference operator[] (multi_difference_type const & d) const
01463     {
01464         return this->m_ptr [total_stride(d.begin())];
01465     }
01466 
01467     next_type begin () const
01468     {
01469         return *this;
01470     }
01471 
01472     next_type end () const
01473     {
01474         next_type ret = *this;
01475         ret += m_shape [level-1];
01476         return ret;
01477     }
01478 
01479     iterator iteratorForDimension(unsigned int d) const
01480     {
01481         vigra_precondition(d <= level,
01482             "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
01483         return iterator(this->m_ptr, &m_stride [d], 0);
01484     }
01485 
01486     template <unsigned int K>
01487     StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
01488     dim()
01489     {
01490         return *this;
01491     }
01492 
01493     StridedMultiIterator<1, T, REFERENCE, POINTER> &
01494     dim0() { return *this; }
01495     StridedMultiIterator<2, T, REFERENCE, POINTER> &
01496     dim1() { return *this; }
01497 
01498   protected:
01499 
01500     difference_type 
01501     total_stride(typename multi_difference_type::const_iterator d) const
01502     {
01503         return d[level]*m_stride[level] + base_type::total_stride(d);
01504     }
01505 };
01506 
01507 /********************************************************/
01508 /*                                                      */
01509 /*                   StridedMultiIterator<N>            */
01510 /*                                                      */
01511 /********************************************************/
01512 
01513 /** \brief A multi-dimensional hierarchical iterator to be used with 
01514            \ref vigra::MultiArrayView if it is not strided.
01515 
01516      See \ref MultiIteratorPage for further documentation.
01517 
01518 <b>\#include</b> <vigra/multi_iterator.hxx>
01519 
01520 Namespace: vigra
01521 */
01522 template <unsigned int N, class T, class REFERENCE, class POINTER>
01523 class StridedMultiIterator 
01524 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
01525 : public StridedMultiIterator<N-1, T, REFERENCE, POINTER>
01526 #endif
01527 {
01528 public:
01529 
01530         /** the type of the parent in the inheritance hierarchy.
01531          */
01532     typedef StridedMultiIterator<N-1, T, REFERENCE, POINTER> base_type;
01533         
01534         /** the iterator's level in the dimension hierarchy
01535          */
01536     enum { level = N-1 };
01537 
01538         /** the iterator's value type
01539          */
01540     typedef T value_type;
01541 
01542         /** reference type (result of operator[])
01543          */
01544     typedef REFERENCE reference;
01545 
01546         /** const reference type (result of operator[] const)
01547          */
01548     typedef const value_type &const_reference;
01549 
01550         /** pointer type
01551          */
01552     typedef POINTER pointer;
01553 
01554         /** const pointer type
01555          */
01556     typedef const value_type *const_pointer;
01557 
01558         /** multi difference type 
01559             (used for offsetting along all axes simultaneously)
01560          */
01561     typedef typename MultiArrayShape<N>::type multi_difference_type;
01562 
01563         /** difference type (used for offsetting)
01564          */
01565     typedef MultiArrayIndex difference_type;
01566     
01567         /** the StridedMultiIterator for the next lower dimension.
01568          */
01569     typedef base_type next_type;
01570 
01571         /** the 1-dimensional iterator for this iterator hierarchy
01572             (result of iteratorForDimension()).
01573         */
01574     typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
01575 
01576         /** the iterator tag (image traverser)
01577         */
01578     typedef multi_dimensional_traverser_tag iterator_category;
01579             
01580     /* use default copy constructor and assignment operator */
01581 
01582         /** default constructor.
01583         */
01584     StridedMultiIterator ()
01585     {}
01586 
01587         /** construct from pointer, strides (offset of a sample to the
01588             next) for every dimension, and the shape.
01589         */
01590     StridedMultiIterator (pointer ptr,
01591                    const difference_type *stride,
01592                    const difference_type *shape)
01593         : base_type (ptr, stride, shape)
01594     {}
01595 
01596 
01597         /** prefix-increment the iterator in it's current dimension
01598          */
01599     void operator++ ()
01600     {
01601         this->m_ptr += this->m_stride [level];
01602     }
01603 
01604         /** prefix-decrement the iterator in it's current dimension
01605          */
01606     void operator-- ()
01607     {
01608         this->m_ptr -= this->m_stride [level];
01609     }
01610 
01611         /** postfix-increment the iterator in it's current dimension
01612          */
01613     StridedMultiIterator operator++ (int)
01614     {
01615         StridedMultiIterator ret = *this;
01616         ++(*this);
01617         return ret;
01618     }
01619 
01620         /** postfix-decrement the iterator in it's current dimension
01621          */
01622     StridedMultiIterator operator-- (int)
01623     {
01624         StridedMultiIterator ret = *this;
01625         --(*this);
01626         return ret;
01627     }
01628 
01629         /** increment the iterator in it's current dimension
01630             by the given value.
01631         */
01632     StridedMultiIterator & operator+= (difference_type n)
01633     {
01634         this->m_ptr += n * this->m_stride [level];
01635         return *this;
01636     }
01637 
01638         /** increment the iterator in all dimensions
01639             by the given offset.
01640         */
01641     StridedMultiIterator & operator+= (multi_difference_type const & d)
01642     {
01643         this->m_ptr += total_stride(d.begin());
01644         return *this;
01645     }
01646 
01647         /** decrement the iterator in it's current dimension
01648             by the given value.
01649         */
01650     StridedMultiIterator & operator-= (difference_type n)
01651     {
01652         this->m_ptr -= n * this->m_stride [level];
01653         return *this;
01654     }
01655 
01656         /** decrement the iterator in all dimensions
01657             by the given offset.
01658         */
01659     StridedMultiIterator & operator-= (multi_difference_type const & d)
01660     {
01661         this->m_ptr -= total_stride(d.begin());
01662         return *this;
01663     }
01664 
01665         /** addition within current dimension
01666          */
01667     StridedMultiIterator operator+ (difference_type n) const
01668     {
01669         StridedMultiIterator ret = *this;
01670         ret += n;
01671         return ret;
01672     }
01673 
01674         /** addition along all dimensions
01675          */
01676     StridedMultiIterator operator+ (multi_difference_type const & d) const
01677     {
01678         StridedMultiIterator ret = *this;
01679         ret += d;
01680         return ret;
01681     }
01682 
01683         /** difference of two iterators in the current dimension.
01684             The result of this operation is undefined if the iterator
01685             doesn't point to element 0 in all dimensions below its current dimension.
01686         */
01687     difference_type operator- (StridedMultiIterator const & d) const
01688     {
01689         return (this->m_ptr - d.m_ptr) / this->m_stride[level];
01690     }
01691 
01692         /** subtraction within current dimension
01693          */
01694     StridedMultiIterator operator- (difference_type n) const
01695     {
01696         StridedMultiIterator ret = *this;
01697         ret -= n;
01698         return ret;
01699     }
01700 
01701         /** subtraction along all dimensions
01702          */
01703     StridedMultiIterator operator- (multi_difference_type const & d) const
01704     {
01705         StridedMultiIterator ret = *this;
01706         ret -= d;
01707         return ret;
01708     }
01709 
01710 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
01711         /** derefenrence item
01712          */
01713     reference operator* () const;
01714 
01715         /** get address of current item
01716          */
01717     pointer get () const;
01718 
01719         /** call method of current item
01720          */
01721     pointer operator->() const;
01722 
01723         /** inequality. True if iterators reference different items.
01724          */
01725     bool operator!= (const StridedMultiIterator &rhs) const;
01726 
01727         /** equality. True if iterators reference the same items.
01728          */
01729     bool operator== (const StridedMultiIterator &rhs) const;
01730 
01731         /** less than.
01732          */
01733     bool operator< (const StridedMultiIterator &rhs) const;
01734 
01735         /** less or equal.
01736          */
01737     bool operator<= (const StridedMultiIterator &rhs) const;
01738 
01739         /** greater than.
01740          */
01741     bool operator> (const StridedMultiIterator &rhs) const;
01742     
01743         /** greater or equal.
01744          */
01745     bool operator>= (const StridedMultiIterator &rhs) const;
01746 #endif
01747 
01748         /** access the array element at the given offset in 
01749         the current dimension.
01750         */
01751     reference operator[] (difference_type n) const
01752     {
01753         return this->m_ptr [n* this->m_stride [level]];
01754     }
01755 
01756         /** access the array element at the given offset.
01757         */
01758     reference operator[] (multi_difference_type const & d) const
01759     {
01760         return this->m_ptr [total_stride(d.begin())];
01761     }
01762 
01763         /** Return the (N-1)-dimensional multi-iterator that points to 
01764             the first (N-1)-dimensional subarray of the 
01765             N-dimensional array this iterator is referring to.
01766             The result is only valid if this iterator refers to location
01767             0 in <em>all</em> dimensions below its current dimension N,
01768             otherwise it is undefined. Usage:
01769 
01770             \code
01771 
01772             StridedMultiIterator<2, int> outer = ...;  // this iterator
01773 
01774             StridedMultiIterator<2, int>::next_type inner = outer.begin();
01775             for(; inner != outer.end(); ++inner)
01776             {
01777                 // manipulate current 1D subimage
01778             }
01779             \endcode
01780         */
01781     next_type begin () const
01782     {
01783         return *this;
01784     }
01785 
01786         /** Return the (N-1)-dimensional multi-iterator that points beyond 
01787             the last (N-1)-dimensional subarray of the 
01788             N-dimensional array this iterator is referring to.
01789             The result is only valid if this iterator refers to location
01790             0 in <em>all</em> dimensions below its current dimension N,
01791             otherwise it is undefined.
01792         */
01793     next_type end () const
01794     {
01795         next_type ret = *this;
01796         ret += this->m_shape [level-1];
01797         return ret;
01798     }
01799 
01800         /** Get a 1-dimensional, STL-compatible iterator for the
01801             given dimension, pointing to the current element of <TT>this</TT>.
01802             Usage:
01803 
01804             \code
01805 
01806             StridedMultiIterator<3, int> outer = ...;  // this iterator
01807 
01808             StridedMultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
01809             StridedMultiIterator<3, int>::iterator end = i + height;
01810             for(; i != end; ++i)
01811             {
01812                 // go down the current column starting at the location of 'outer'
01813             }
01814             \endcode            
01815         */
01816     iterator iteratorForDimension(unsigned int d) const
01817     {
01818         vigra_precondition(d <= level,
01819             "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
01820         return iterator(this->m_ptr, &this->m_stride [d], 0);
01821     }
01822         /** Return the multi-iterator that operates on dimension K in order
01823             to manipulate this dimension directly. Usage:
01824                
01825             \code
01826                 
01827             StridedMultiIterator<3, int> i3 = ...;
01828                 
01829             i3.template dim<2>()++;  // increment outer dimension
01830             i3.template dim<0>()++;  // increment inner dimension
01831             \endcode
01832             
01833             For convenience, the same functionality is also available
01834             as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
01835             
01836             \code
01837                 
01838             StridedMultiIterator<3, int> i3 = ...;
01839                 
01840             i3.dim2()++;  // increment outer dimension
01841             i3.dim0()++;  // increment inner dimension
01842             \endcode            
01843         */
01844     template <unsigned int K>
01845     StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
01846     dim()
01847     {
01848         return *this;
01849     }
01850 
01851     StridedMultiIterator<1, T, REFERENCE, POINTER> &
01852     dim0() { return *this; }
01853     StridedMultiIterator<2, T, REFERENCE, POINTER> &
01854     dim1() { return *this; }
01855     StridedMultiIterator<3, T, REFERENCE, POINTER> &
01856     dim2() { return *this; }
01857     StridedMultiIterator<4, T, REFERENCE, POINTER> &
01858     dim3() { return *this; }
01859     StridedMultiIterator<5, T, REFERENCE, POINTER> &
01860     dim4() { return *this; }
01861 
01862   protected:
01863 
01864     difference_type 
01865     total_stride(typename multi_difference_type::const_iterator d) const
01866     {
01867         return d[level]*this->m_stride[level] + base_type::total_stride(d);
01868     }
01869 
01870 };
01871 
01872 namespace detail {
01873 
01874 template <unsigned int M>
01875 struct MoveToScanOrderIndex
01876 {
01877     template <class Shape, class Ptr>
01878     static void 
01879     exec(MultiArrayIndex newIndex, Shape const & shape,
01880          Shape & point, Ptr & p, Shape const & strides)
01881     {
01882         enum { N = Shape::static_size };
01883         MultiArrayIndex newPos = newIndex % shape[N-1-M];
01884         p += (newPos - point[N-1-M]) * strides[N-1-M];
01885         point[N-1-M] = newPos;
01886         MoveToScanOrderIndex<M-1>::exec(newIndex / shape[N-1-M], shape, point, p, strides);
01887     }
01888     
01889     template <class Shape, class Ptr1, class Ptr2>
01890     static void 
01891     exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point, 
01892          Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2)
01893     {
01894         enum { N = Shape::static_size };
01895         MultiArrayIndex newPos = newIndex % shape[N-1-M];
01896         p1 += (newPos - point[N-1-M]) * strides1[N-1-M];
01897         p2 += (newPos - point[N-1-M]) * strides2[N-1-M];
01898         point[N-1-M] = newPos;
01899         MoveToScanOrderIndex<M-1>::exec(newIndex / shape[N-1-M], shape, point, 
01900                                          p1, strides1, p2, strides2);
01901     }
01902 };
01903 
01904 template <>
01905 struct MoveToScanOrderIndex<0>
01906 {
01907     template <class Shape, class Ptr>
01908     static void 
01909     exec(MultiArrayIndex newIndex, Shape const & shape,
01910          Shape & point, Ptr & p, Shape const & strides)
01911     {
01912         enum { N = Shape::static_size }; 
01913         MultiArrayIndex newPos = newIndex % shape[N-1];
01914         p += (newPos - point[N-1]) * strides[N-1];
01915         point[N-1] = newPos;
01916     }
01917     
01918     template <class Shape, class Ptr1, class Ptr2>
01919     static void 
01920     exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point, 
01921          Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2)
01922     {
01923         enum { N = Shape::static_size }; 
01924         MultiArrayIndex newPos = newIndex % shape[N-1];
01925         p1 += (newPos - point[N-1]) * strides1[N-1];
01926         p2 += (newPos - point[N-1]) * strides2[N-1];
01927         point[N-1] = newPos;
01928     }
01929 };
01930 
01931 #if 0 // alternative implementation, may be faster on some machines
01932 template <unsigned int M>
01933 struct MoveToScanOrderIndex
01934 {
01935     template <class Shape, class Ptr>
01936     static void 
01937     exec(MultiArrayIndex & newIndex, Shape const & shape,
01938          Shape & point, Ptr & p, Shape const & strides, MultiArrayIndex shapeStride = 1)
01939     {
01940         enum { N = Shape::static_size };
01941         MoveToScanOrderIndex<M-1>::exec(newIndex, shape, point, p, strides, shapeStride*shape[N-1-M]);
01942         MultiArrayIndex newPos = newIndex / shapeStride;
01943         p += (newPos - point[N-1-M]) * strides[N-1-M];
01944         point[N-1-M] = newPos;
01945         newIndex %= shapeStride;
01946     }
01947     
01948     template <class Shape, class Ptr1, class Ptr2>
01949     static void 
01950     exec(MultiArrayIndex & newIndex, Shape const & shape, Shape & point, 
01951          Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2, 
01952          MultiArrayIndex shapeStride = 1)
01953     {
01954         enum { N = Shape::static_size };
01955         MoveToScanOrderIndex<M-1>::exec(newIndex, shape, point, 
01956                                          p1, strides1, p2, strides2, shapeStride*shape[N-1-M]);
01957         MultiArrayIndex newPos = newIndex / shapeStride;
01958         p1 += (newPos - point[N-1-M]) * strides1[N-1-M];
01959         p2 += (newPos - point[N-1-M]) * strides2[N-1-M];
01960         point[N-1-M] = newPos;
01961         newIndex %= shapeStride;
01962     }
01963 };
01964 
01965 template <>
01966 struct MoveToScanOrderIndex<0>
01967 {
01968     template <class Shape, class Ptr>
01969     static void 
01970     exec(MultiArrayIndex & newIndex, Shape const & shape,
01971          Shape & point, Ptr & p, Shape const & strides, MultiArrayIndex shapeStride)
01972     {
01973         enum { N = Shape::static_size }; 
01974         MultiArrayIndex newPos = newIndex / shapeStride;
01975         p += (newPos - point[N-1]) * strides[N-1];
01976         point[N-1] = newPos;
01977         newIndex %= shapeStride;
01978     }
01979     
01980     template <class Shape, class Ptr1, class Ptr2>
01981     static void 
01982     exec(MultiArrayIndex & newIndex, Shape const & shape, Shape & point, 
01983          Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2, 
01984          MultiArrayIndex shapeStride)
01985     {
01986         enum { N = Shape::static_size }; 
01987         MultiArrayIndex newPos = newIndex / shapeStride;
01988         p1 += (newPos - point[N-1]) * strides1[N-1];
01989         p2 += (newPos - point[N-1]) * strides2[N-1];
01990         point[N-1] = newPos;
01991         newIndex %= shapeStride;
01992     }
01993 };
01994 #endif
01995 
01996 }
01997 
01998     /** \brief Sequential iterator for MultiArrayView.
01999         
02000         This iterator provides STL-compatible random access iterator functionality for arbitrary 
02001         \ref MultiArrayView instances, regardless of their shapes and strides. The
02002         class uses an implementation that minimizes speed penalties that could result from 
02003         non-trivial strides. The <i>scan-order</i> is defined such that dimensions are iterated 
02004         from front to back (first to last).
02005         
02006         You normally construct instances of this class by calling \ref MultiArrayView::begin() 
02007         and \ref MultiArrayView::end(). 
02008         
02009         The iterator supports all functions listed in the STL documentation for 
02010         <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
02011     */
02012 template <unsigned int N, class T, class REFERENCE, class POINTER, unsigned int M = N>
02013 class StridedScanOrderIterator
02014 #ifndef DOXYGEN  // doxygen doesn't understand this inheritance
02015 : protected StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1>
02016 #endif
02017 {
02018     typedef StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1> base_type;
02019     enum { level = M-1 };
02020 
02021   public:
02022 
02023     typedef typename base_type::value_type value_type;
02024     typedef typename base_type::pointer pointer;
02025     typedef typename base_type::reference reference;
02026     typedef typename base_type::const_reference const_reference;
02027     typedef typename base_type::shape_type shape_type;
02028     typedef MultiArrayIndex difference_type;
02029     typedef StridedScanOrderIterator iterator;
02030     typedef std::random_access_iterator_tag iterator_category;
02031     
02032     StridedScanOrderIterator()
02033     {}
02034     
02035     StridedScanOrderIterator(pointer i, 
02036                              shape_type const & shape, shape_type const & strides)
02037     : base_type(i, shape, strides)
02038     {}
02039 
02040     StridedScanOrderIterator & operator++()
02041     {
02042         base_type::operator++();
02043         if(this->point_[level-1] == this->shape_[level-1]) 
02044         {
02045             base_type::reset();
02046             this->i_ += this->strides_[level];
02047             ++this->point_[level];
02048         }
02049         return *this;
02050     }
02051 
02052     StridedScanOrderIterator operator++(int)
02053     {
02054         StridedScanOrderIterator res(*this);
02055         ++*this;
02056         return res;
02057     }
02058 
02059     StridedScanOrderIterator & operator+=(MultiArrayIndex i)
02060     {
02061         this->moveToScanOrderIndex(this->index_+i);
02062         return *this;
02063     }
02064 
02065     StridedScanOrderIterator & operator--()
02066     {
02067         base_type::operator--();
02068         if(this->point_[level-1] == -1) 
02069         {
02070             base_type::inverseReset();
02071             this->i_ -= this->strides_[level];
02072             --this->point_[level];
02073         }
02074         return *this;
02075     }
02076 
02077     StridedScanOrderIterator operator--(int)
02078     {
02079         StridedScanOrderIterator res(*this);
02080         --*this;
02081         return res;
02082     }
02083 
02084     StridedScanOrderIterator & operator-=(MultiArrayIndex i)
02085     {
02086         return operator+=(-i);
02087     }
02088 
02089     StridedScanOrderIterator getEndIterator() const
02090     {
02091         StridedScanOrderIterator res(*this);
02092         res.moveToScanOrderIndex(prod(this->shape_));
02093         return res;
02094     }
02095 
02096     bool atBorder() const
02097     {
02098         return base_type::atBorder() || 
02099                 this->point_[level] == 0 || 
02100                 this->point_[level] == this->shape_[level] - 1;
02101     }
02102     
02103     unsigned int neighborhoodType() const
02104     {
02105         unsigned int res = base_type::neighborhoodType();
02106         if(this->point_[level] == 0)
02107             res |= (1 << 2*level);
02108         if(this->point_[level] == this->shape_[level]-1)
02109             res |= (2 << 2*level);
02110         return res;
02111     }
02112     
02113     StridedScanOrderIterator operator+(MultiArrayIndex d) const
02114     {
02115         return StridedScanOrderIterator(*this) += d;
02116     }
02117 
02118     StridedScanOrderIterator operator-(MultiArrayIndex d) const
02119     {
02120         return StridedScanOrderIterator(*this) -= d;
02121     }
02122     
02123     MultiArrayIndex operator-(StridedScanOrderIterator const & r) const
02124     {
02125         return base_type::operator-(r);
02126     }
02127 
02128     bool operator==(StridedScanOrderIterator const & r)
02129     {
02130         return base_type::operator==(r);
02131     }
02132 
02133     bool operator!=(StridedScanOrderIterator const & r) const
02134     {
02135         return base_type::operator!=(r);
02136     }
02137 
02138     bool operator<(StridedScanOrderIterator const & r) const
02139     {
02140         return base_type::operator<(r);
02141     }
02142 
02143     bool operator<=(StridedScanOrderIterator const & r) const
02144     {
02145         return base_type::operator<=(r);
02146     }
02147 
02148     bool operator>(StridedScanOrderIterator const & r) const
02149     {
02150         return base_type::operator>(r);
02151     }
02152 
02153     bool operator>=(StridedScanOrderIterator const & r) const
02154     {
02155         return base_type::operator>=(r);
02156     }
02157 
02158     using base_type::point;
02159     using base_type::shape;
02160     using base_type::strides;
02161     using base_type::ptr;
02162     using base_type::index;
02163     using base_type::operator*;
02164     using base_type::operator->;
02165     using base_type::operator[];
02166 
02167   protected:
02168     void reset()
02169     {
02170         this->i_ -= this->shape_[level]*this->strides_[level];
02171         this->point_[level] = 0;
02172     }
02173 
02174     void inverseReset()
02175     {
02176         this->i_ += this->shape_[level]*this->strides_[level];
02177         this->point_[level] = this->shape_[level]-1;
02178     }
02179     
02180     template <class Ptr>
02181     void increment(Ptr & p2, shape_type const & strides2)
02182     {
02183         base_type::increment(p2, strides2);
02184         if(this->point_[level-1] == this->shape_[level-1]) 
02185         {
02186             base_type::reset();
02187             this->i_ += this->strides_[level];
02188             p2 += strides2[level] - this->shape_[level-1]*strides2[level-1];
02189             ++this->point_[level];
02190         }
02191     }
02192     
02193     template <class Ptr>
02194     void decrement(Ptr & p2, shape_type const & strides2)
02195     {
02196         base_type::decrement(p2, strides2);
02197         if(this->point_[level-1] == -1) 
02198         {
02199             base_type::inverseReset();
02200             this->i_ -= this->strides_[level];
02201             p2 -= strides2[level] - this->shape_[level-1]*strides2[level-1];
02202             --this->point_[level];
02203         }
02204     }
02205 };
02206 
02207 template <unsigned int N, class T, class REFERENCE, class POINTER>
02208 class StridedScanOrderIterator<N, T, REFERENCE, POINTER, 1>
02209 {
02210     enum { level = 0 };
02211 
02212   public:
02213 
02214     typedef T value_type;
02215     typedef POINTER pointer;
02216     typedef T const * const_pointer;
02217     typedef REFERENCE reference;
02218     typedef T const & const_reference;
02219     typedef typename MultiArrayShape<N>::type shape_type;
02220     typedef MultiArrayIndex difference_type;
02221     typedef StridedScanOrderIterator iterator;
02222     typedef std::random_access_iterator_tag iterator_category;
02223 
02224     StridedScanOrderIterator()
02225     : i_((pointer)0),
02226       index_(0)
02227     {}
02228     
02229     StridedScanOrderIterator(pointer i, 
02230                              shape_type const & shape, shape_type const & strides)
02231     : i_(i),
02232       shape_(shape),
02233       strides_(strides),
02234       index_(0)
02235     {}
02236 
02237     StridedScanOrderIterator & operator++()
02238     {
02239         i_ += strides_[level];
02240         ++point_[level];
02241         ++index_;
02242         return *this;
02243     }
02244 
02245     StridedScanOrderIterator operator++(int)
02246     {
02247         StridedScanOrderIterator res(*this);
02248         ++*this;
02249         return res;
02250     }
02251 
02252     StridedScanOrderIterator & operator+=(MultiArrayIndex i)
02253     {
02254         this->moveToScanOrderIndex(index_+i);
02255         return *this;
02256     }
02257     
02258     StridedScanOrderIterator & operator--()
02259     {
02260         i_ -= strides_[level];
02261         --point_[level];
02262         --index_;
02263         return *this;
02264     }
02265 
02266     StridedScanOrderIterator operator--(int)
02267     {
02268         StridedScanOrderIterator res(*this);
02269         --this;
02270         return res;
02271     }
02272 
02273     StridedScanOrderIterator & operator-=(MultiArrayIndex i)
02274     {
02275         return operator+=(-i);
02276     }
02277     
02278     reference operator*()
02279     {
02280         return *i_;
02281     }
02282 
02283     const_reference operator*() const
02284     {
02285         return *i_;
02286     }
02287     
02288     pointer operator->()
02289     {
02290         return i_;
02291     }
02292 
02293     const_pointer operator->() const
02294     {
02295         return i_;
02296     }
02297 
02298     pointer ptr()
02299     {
02300         return i_;
02301     }
02302 
02303     const_pointer ptr() const
02304     {
02305         return i_;
02306     }
02307 
02308     reference operator[](MultiArrayIndex i)
02309     {
02310         StridedScanOrderIterator t(*this);
02311         t.moveToScanOrderIndex(index_+i);
02312         return *t;
02313     }
02314 
02315     const_reference operator[](MultiArrayIndex i) const
02316     {
02317         StridedScanOrderIterator t(*this);
02318         t.moveToScanOrderIndex(index_+i);
02319         return *t;
02320     }
02321 
02322     StridedScanOrderIterator
02323     operator+(MultiArrayIndex d) const
02324     {
02325         return StridedScanOrderIterator(*this) += d;
02326     }
02327 
02328     StridedScanOrderIterator
02329     operator-(MultiArrayIndex d) const
02330     {
02331         return StridedScanOrderIterator(*this) -= d;
02332     }
02333     
02334     MultiArrayIndex
02335     operator-(StridedScanOrderIterator const & r) const
02336     {
02337         return index() - r.index();
02338     }
02339 
02340     bool
02341     operator==(StridedScanOrderIterator const & r)
02342     {
02343         return index() == r.index();
02344     }
02345 
02346     bool
02347     operator!=(StridedScanOrderIterator const & r) const
02348     {
02349         return index() != r.index();
02350     }
02351 
02352     bool
02353     operator<(StridedScanOrderIterator const & r) const
02354     {
02355         return index() < r.index();
02356     }
02357 
02358     bool
02359     operator<=(StridedScanOrderIterator const & r) const
02360     {
02361         return index() <= r.index();
02362     }
02363 
02364     bool
02365     operator>(StridedScanOrderIterator const & r) const
02366     {
02367         return index() > r.index();
02368     }
02369 
02370     bool
02371     operator>=(StridedScanOrderIterator const & r) const
02372     {
02373         return index() >= r.index();
02374     }
02375 
02376 
02377     bool atBorder() const
02378     {
02379         return point_[level] == 0 || point_[level] == shape_[level] - 1;
02380     }
02381     
02382     MultiArrayIndex index() const
02383     {
02384         return index_;
02385     }
02386     
02387     shape_type const & point() const
02388     {
02389         return point_;
02390     }
02391     
02392     shape_type const & shape() const
02393     {
02394         return shape_;
02395     }
02396     
02397     shape_type const & strides() const
02398     {
02399         return strides_;
02400     }
02401     
02402     StridedScanOrderIterator getEndIterator() const
02403     {
02404         StridedScanOrderIterator res(*this);
02405         res.moveToScanOrderIndex(prod(shape_));
02406         return res;
02407     }
02408     
02409     unsigned int neighborhoodType() const
02410     {
02411         unsigned int res = 0;
02412         if(this->point_[level] == 0)
02413             res |= 1;
02414         if(this->point_[level] == this->shape_[level]-1)
02415             res |= 2;
02416         return res;
02417     }
02418 
02419   protected:
02420     void reset()
02421     {
02422         i_ -= shape_[level]*strides_[level];
02423         point_[level] = 0;
02424     }
02425     
02426     void inverseReset()
02427     {
02428         i_ += shape_[level]*strides_[level];
02429         point_[level] = shape_[level] - 1;
02430     }
02431     
02432     void moveToScanOrderIndex(MultiArrayIndex newIndex)
02433     {
02434         index_ = newIndex;
02435         detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i_, strides_);
02436     }
02437     
02438     template <class Ptr>
02439     void increment(Ptr & p2, shape_type const & strides2)
02440     {
02441         operator++();
02442         p2 += strides2[level];
02443     }
02444     
02445     template <class Ptr>
02446     void decrement(Ptr & p2, shape_type const & strides2)
02447     {
02448         operator--();
02449         p2 -= strides2[level];
02450     }
02451     
02452     template <class Ptr>
02453     void moveToScanOrderIndex(MultiArrayIndex newIndex, Ptr & p2, shape_type const & strides2)
02454     {
02455         index_ = newIndex;
02456         detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i_, strides_, p2, strides2);
02457     }
02458 
02459     pointer i_;
02460     shape_type point_, shape_, strides_;
02461     MultiArrayIndex index_;
02462 };
02463 
02464 
02465 //@}
02466 
02467 } // namespace vigra
02468 
02469 #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.8.0 (20 Sep 2011)