VIGRA - vigra/multi_iterator.hxx Source File

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

| vigra/multi_iterator.hxx |
--- | --- | ---

    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)