[ 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.4.0, Dec 21 2005 ) */ 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 "vigra/tinyvector.hxx" 00045 #include "vigra/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<N, ..></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<ptrdiff_t, N></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<K+1, T, ...></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) |
html generated using doxygen and Python
|