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

details vigra/multi_iterator.hxx VIGRA

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.5.0 (7 Dec 2006)