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