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

multi_iterator.hxx
1 /************************************************************************/
2 /* */
3 /* Copyright 2003-2008 by Gunnar Kedenburg and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* ( Version 1.3.0, Sep 10 2004 ) */
7 /* The VIGRA Website is */
8 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
9 /* Please direct questions, bug reports, and contributions to */
10 /* ullrich.koethe@iwr.uni-heidelberg.de or */
11 /* vigra@informatik.uni-hamburg.de */
12 /* */
13 /* Permission is hereby granted, free of charge, to any person */
14 /* obtaining a copy of this software and associated documentation */
15 /* files (the "Software"), to deal in the Software without */
16 /* restriction, including without limitation the rights to use, */
17 /* copy, modify, merge, publish, distribute, sublicense, and/or */
18 /* sell copies of the Software, and to permit persons to whom the */
19 /* Software is furnished to do so, subject to the following */
20 /* conditions: */
21 /* */
22 /* The above copyright notice and this permission notice shall be */
23 /* included in all copies or substantial portions of the */
24 /* Software. */
25 /* */
26 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
27 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
28 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
29 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
30 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
31 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
32 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
33 /* OTHER DEALINGS IN THE SOFTWARE. */
34 /* */
35 /************************************************************************/
36 
37 
38 #ifndef VIGRA_MULTI_ITERATOR_HXX
39 #define VIGRA_MULTI_ITERATOR_HXX
40 
41 #include <sys/types.h>
42 #include "tinyvector.hxx"
43 #include "iteratortags.hxx"
44 
45 namespace vigra {
46 
47 
48 template <unsigned int N, class T,
49  class REFERENCE = T &, class POINTER = T *> class MultiIterator;
50 template <unsigned int N, class T,
51  class REFERENCE = T &, class POINTER = T *> class StridedMultiIterator;
52 
53 /** \page MultiIteratorPage Multi-dimensional Array Iterators
54 
55  General iterators for arrays of arbitrary dimension.
56 
57 
58 <p>
59 <UL style="list-style-image:url(documents/bullet.gif)">
60 <LI> \ref vigra::MultiArrayShape
61  <BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayView or \ref vigra::MultiIterator</em>
62 <LI> \ref vigra::MultiIterator
63  <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArrayView</em>
64 <LI> \ref vigra::StridedMultiIterator
65  <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayView</em>
66 <LI> \ref vigra::StridedScanOrderIterator
67  <BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \ref vigra::MultiArrayView</em>
68 <LI> \ref vigra::CoupledScanOrderIterator
69  <BR>&nbsp;&nbsp;&nbsp;<em>Iterate over multiple images simultaneously in scan order</em>
70 </UL>
71 </p>
72 
73 <p>
74  The Multidimensional Iterator concept allows navigation on arrays
75  of arbitrary dimension. It provides two modes of iteration:
76  <em>direct traversal</em>, and <em>hierarchical traversal</em>.
77  In general, hierarchical traversal will be faster, while only
78  direct traversal allows for true random access in all dimensions.
79  Via the <tt>dim<K>()</tt> function, operations applying to a particular
80  dimension can be used in the direct traversal mode. In contrast,
81  direct traversal functions should not be used in the hierarchical mode
82  because the hierarchical functions are only well-defined if the
83  iterator points to element 0 in all dimensions below its current dimension.
84  The current dimension of a <tt>MultiIterator<N, ...></tt> is <tt>N-1</tt>.
85 </p>
86 <h3>General Requirements for MultiIterator</h3>
87 <p>
88 <table border=2 cellspacing=0 cellpadding=2 width="100%">
89 <tr><th colspan=2>
90  Local Types
91  </th><th>
92  Meaning
93  </th>
94 </tr>
95 <tr><td colspan=2>
96  <tt>MultiIterator::value_type</tt></td><td>the underlying arrays's pixel type</td>
97 </tr>
98 <tr><td colspan=2>
99  <tt>MultiIterator::reference</tt></td>
100  <td>the iterator's reference type (return type of <TT>*iter</TT>). Will be
101  <tt>value_type &</tt> for a mutable iterator, and convertible to
102  <tt>value_type const &</tt> for a const iterator.</td>
103 </tr>
104 <tr><td colspan=2>
105  <tt>MultiIterator::pointer</tt></td>
106  <td>the iterator's pointer type (return type of <TT>iter.operator->()</TT>). Will be
107  <tt>value_type *</tt> for a mutable iterator, and convertible to
108  <tt>value_type const *</tt> for a const iterator.</td>
109 </tr>
110 <tr><td colspan=2>
111  <tt>MultiIterator::iterator_category</tt></td>
112  <td>the iterator tag (<tt>vigra::multi_dimensional_traverser_tag</tt>)</td>
113 </tr>
114 <tr><th>
115  Operation
116  </th><th>
117  Result
118  </th><th>
119  Semantics
120  </th>
121 </tr>
122 <tr><td colspan=2>
123  <tt>MultiIterator k;</tt></td><td>default constructor</td>
124 </tr>
125 <tr><td colspan=2>
126  <tt>MultiIterator k(i);</tt></td><td>copy constructor</td>
127 </tr>
128 <tr>
129  <td><tt>k = i</tt></td>
130  <td><tt>MultiIterator &</tt></td><td>assignment</td>
131 </tr>
132 <tr>
133  <td><tt>i == j</tt></td><td><tt>bool</tt></td>
134  <td>equality (iterators point to the same element)</td>
135 </tr>
136 <tr>
137  <td><tt>i != j</tt></td><td><tt>bool</tt></td>
138  <td>inequality (iterators don't point to the same element)</td>
139 </tr>
140 <tr>
141  <td><tt>*i</tt></td><td><tt>MultiIterator::reference</tt></td>
142  <td>access the current element</td>
143 </tr>
144 <tr>
145  <td><tt>i->member()</tt></td><td>depends on operation</td>
146  <td>call member function of underlying pixel type via <tt>operator-></tt> of iterator</td>
147 </tr>
148 </table>
149 </p>
150 <h3>Requirements for Direct Traversal</h3>
151 <p>
152 <table border=2 cellspacing=0 cellpadding=2 width="100%">
153 <tr><th colspan=2>
154  Local Types
155  </th><th>
156  Meaning
157  </th>
158 </tr>
159 <tr><td colspan=2>
160  <tt>MultiIterator::multi_difference_type</tt></td>
161  <td>the iterator's multi-dimensional difference type (<TT>TinyVector<MultiArrayIndex, N></TT>)</td>
162 </tr>
163 <tr><th>
164  Operation
165  </th><th>
166  Result
167  </th><th>
168  Semantics
169  </th>
170 </tr>
171 <tr>
172  <td><tt>i += diff</tt></td><td><tt>MultiIterator &</tt></td>
173  <td>add offset to current position</td>
174 </tr>
175 <tr>
176  <td><tt>i -= diff</tt></td><td><tt>MultiIterator &</tt></td>
177  <td>subtract offset from current position</td>
178 </tr>
179 <tr>
180  <td><tt>i + diff</tt></td><td><tt>MultiIterator</tt></td>
181  <td>create traverser by adding offset</td>
182 </tr>
183 <tr>
184  <td><tt>i - diff</tt></td><td><tt>MultiIterator</tt></td>
185  <td>create traverser by subtracting offset</td>
186 </tr>
187 <tr>
188  <td><tt>i[diff]</tt></td><td><tt>MultiIterator::reference</tt></td>
189  <td>access element at offset <tt>diff</tt></td>
190 </tr>
191 <tr>
192  <td><tt>i.dim<K>()</tt></td><td><tt>MultiIterator<K+1, T, ...></tt></td>
193  <td>Access the traverser with the current dimension set to K. Typically used to call
194  navigation functions referring to a particular dimension.<br>
195  Example (assuming <tt>i, j</tt> are 3-dimensional):<br>
196  \code
197  i.dim<0>()++; // increment dimension 0
198  i.dim<1>()++; // increment dimension 1
199  i.dim<2>()++; // increment dimension 2
200 
201  j += MultiIterator::multi_difference_type(1,1,1); // same effect
202  \endcode
203  </td>
204 </tr>
205 <tr><td colspan=3>
206  <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
207  <tt>diff</tt> is of type <tt>MultiIterator::multi_difference_type</tt><br>
208  <tt>K</tt> is an integer compile-time constant
209  </td>
210 </tr>
211 </table>
212 </p>
213 <p>
214 Note that it is impossible to support an <tt>operator-</tt> between two iterators which returns
215 a <tt>MultiIterator::multi_difference_type</tt> because it is impossible to decide to which
216 dimension a difference applies. Consider for example, a 2-dimensional iterator <tt>i</tt>, and
217 let <tt>j = i + multi_difference_type(width, 0)</tt>, <tt>k = i + multi_difference_type(0,1)</tt>,
218 where <tt>width</tt> is the array's total width. In general, <tt>j</tt> and <tt>k</tt> point to
219 the same memory location, so that the two cases cannot easily be distinguished (it is possible,
220 but iterator performance will suffer significantly, as is experienced with
221 \ref vigra::ImageIterator where differencing is allowed).
222 </p>
223 
224 <h3>Requirements for Hierarchical Traversal</h3>
225 <p>
226 <table border=2 cellspacing=0 cellpadding=2 width="100%">
227 <tr><th colspan=2>
228  Local Types
229  </th><th>
230  Meaning
231  </th>
232 </tr>
233 <tr><td colspan=2>
234  <tt>MultiIterator::difference_type</tt></td>
235  <td>the iterator's difference type (<TT>MultiArrayIndex</TT>)</td>
236 </tr>
237 <tr><td colspan=2>
238  <tt>MultiIterator::next_type</tt></td><td>type of the next iterator
239  (referring to the next lower dimension) in the hierarchy</td>
240 </tr>
241 <tr><th>
242  Operation
243  </th><th>
244  Result
245  </th><th>
246  Semantics
247  </th>
248 </tr>
249 <tr>
250  <td><tt>++i</tt></td><td><tt>MultiIterator &</tt></td>
251  <td>pre-increment iterator in its current dimension</td>
252 </tr>
253 <tr>
254  <td><tt>i++</tt></td><td><tt>MultiIterator</tt></td>
255  <td>post-increment iterator in its current dimension</td>
256 </tr>
257 <tr>
258  <td><tt>--i</tt></td><td><tt>MultiIterator &</tt></td>
259  <td>pre-decrement iterator in its current dimension</td>
260 </tr>
261 <tr>
262  <td><tt>i--</tt></td><td><tt>MultiIterator</tt></td>
263  <td>post-decrement iterator in its current dimension</td>
264 </tr>
265 <tr>
266  <td><tt>i += d</tt></td><td><tt>MultiIterator &</tt></td>
267  <td>add <tt>d</tt> in current dimension</td>
268 </tr>
269 <tr>
270  <td><tt>i -= d</tt></td><td><tt>MultiIterator &</tt></td>
271  <td>subtract <tt>d</tt> in from dimension</td>
272 </tr>
273 <tr>
274  <td><tt>i + d</tt></td><td><tt>MultiIterator</tt></td>
275  <td>create new iterator by adding <tt>d</tt> in current dimension</td>
276 </tr>
277 <tr>
278  <td><tt>i - d</tt></td><td><tt>MultiIterator</tt></td>
279  <td>create new iterator by subtracting <tt>d</tt> in current dimension</td>
280 </tr>
281 <tr>
282  <td><tt>i - j</tt></td><td><tt>difference_type</tt></td>
283  <td>difference of <tt>i</tt> and <tt>j</tt> in the current dimension<br>
284  <em>Note:</em> The result of this operation is undefined if the iterator
285  doesn't point to element 0 in all dimensions below its current dimension.</td>
286 </tr>
287 <tr>
288  <td><tt>i < j</tt></td><td><tt>bool</tt></td>
289  <td><tt>i - j < 0</tt><br>
290  <em>Note:</em> The result of this operation is undefined if the iterator
291  doesn't point to element 0 in all dimensions below its current dimension.</td>
292 </tr>
293 <tr>
294  <td><tt>i[d]</tt></td><td><tt>MultiIterator::reference</tt></td>
295  <td>access element by adding offset <tt>d</tt> in current dimension</td>
296 </tr>
297 <tr>
298  <td><tt>i.begin()</tt></td><td><tt>next_type</tt></td>
299  <td>create the hierarchical iterator pointing to the first element in the
300  next lower dimension.<br>
301  <em>Note:</em> The result of this operation is undefined if the iterator
302  doesn't point to element 0 in all dimensions below its current dimension.<br>
303  Usage:<br>
304  \code
305  MultiIterator<3, int> i3 = ..., end3 = ...;
306  for(; i3 != end3; ++i3)
307  {
308  MultiIterator<3, int>::next_type i2 = i3.begin(), end2 = i3.end();
309  for(; i2 != end2; ++i2)
310  {
311  MultiIterator<3, int>::next_type::next_type i1 = i2.begin(), end1 = i2.end();
312  for(; i1 != end1; ++i1)
313  {
314  ... // do something with the current element
315  }
316  }
317  }
318 
319  \endcode
320  </td>
321 </tr>
322 <tr>
323  <td><tt>i.end()</tt></td><td><tt>next_type</tt></td>
324  <td>create the hierarchical iterator pointing to the past-the-end location in the
325  next lower dimension.<br>
326  <em>Note:</em> The result of this operation is undefined if the iterator
327  doesn't point to element 0 in all dimensions below its current dimension.</td>
328 </tr>
329 <tr><td colspan=3>
330  <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
331  <tt>d</tt> is of type <tt>MultiIterator::difference_type</tt>
332  </td>
333 </tr>
334 </table>
335 </p>
336 
337 */
338 
339 /** \addtogroup MultiIteratorGroup Multi-dimensional Array Iterators
340 
341  \brief General iterators for arrays of arbitrary dimension.
342 */
343 //@{
344 
345  /** Index type for a single dimension of a MultiArrayView or
346  MultiArray.
347  */
348 typedef std::ptrdiff_t MultiArrayIndex;
349 
350  /** Traits class for the difference type of all MultiIterator, MultiArrayView, and
351  MultiArray variants.
352  */
353 template <unsigned int N>
355 {
356  public:
357  /** The difference type of all MultiIterator, MultiArrayView, and
358  MultiArray variants.
359  */
361 };
362 
363 typedef MultiArrayShape<1>::type Shape1; ///< shape type for MultiArray<1, T>
364 typedef MultiArrayShape<2>::type Shape2; ///< shape type for MultiArray<2, T>
365 typedef MultiArrayShape<3>::type Shape3; ///< shape type for MultiArray<3, T>
366 typedef MultiArrayShape<4>::type Shape4; ///< shape type for MultiArray<4, T>
367 typedef MultiArrayShape<5>::type Shape5; ///< shape type for MultiArray<5, T>
368 
369 template <class POINTER>
370 struct MultiIteratorStrideTraits
371 {
372  typedef MultiArrayIndex stride_type;
373  typedef const stride_type* stride_array_type;
374  typedef stride_array_type shape_array_type;
375  static stride_array_type shift(stride_array_type s, unsigned d)
376  {
377  return s + d;
378  }
379 };
380 
381 
382 /********************************************************/
383 /* */
384 /* MultiIterator */
385 /* */
386 /********************************************************/
387 
388 template <unsigned int N, class T, class REFERENCE, class POINTER>
389 class MultiIterator;
390 
391 /********************************************************/
392 /* */
393 /* MultiIterator<1> */
394 /* */
395 /********************************************************/
396 
397 //
398 template <class T, class REFERENCE, class POINTER>
399 class MultiIterator<1, T, REFERENCE, POINTER>
400 {
401  public:
402  enum { level = 0 };
403  typedef T value_type;
404  typedef REFERENCE reference;
405  typedef const value_type &const_reference;
406  typedef POINTER pointer;
407  typedef const value_type *const_pointer;
408  typedef typename MultiArrayShape<1>::type multi_difference_type;
409  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
410  typedef typename stride_traits::stride_type difference_type;
411  typedef typename stride_traits::stride_array_type difference_array_type;
412  typedef typename stride_traits::shape_array_type shape_array_type;
413  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
414  typedef std::random_access_iterator_tag iterator_category;
415 
416  protected:
417  pointer m_ptr;
418 
419  public:
420  MultiIterator ()
421  : m_ptr (0)
422  {}
423 
424  MultiIterator (pointer ptr,
425  const difference_array_type &,
426  const shape_array_type &)
427  : m_ptr (ptr)
428  {}
429 
430  void operator++ ()
431  {
432  ++m_ptr;
433  }
434 
435  void operator-- ()
436  {
437  --m_ptr;
438  }
439 
441  {
442  MultiIterator ret = *this;
443  ++(*this);
444  return ret;
445  }
446 
448  {
449  MultiIterator ret = *this;
450  --(*this);
451  return ret;
452  }
453 
455  {
456  m_ptr += n;
457  return *this;
458  }
459 
461  {
462  m_ptr += d[level];
463  return *this;
464  }
465 
467  {
468  m_ptr -= n;
469  return *this;
470  }
471 
473  {
474  m_ptr -= d[level];
475  return *this;
476  }
477 
479  {
480  MultiIterator ret = *this;
481  ret += n;
482  return ret;
483  }
484 
486  {
487  MultiIterator ret = *this;
488  ret += d;
489  return ret;
490  }
491 
492  difference_type operator- (MultiIterator const & d) const
493  {
494  return (m_ptr - d.m_ptr);
495  }
496 
498  {
499  MultiIterator ret = *this;
500  ret -= n;
501  return ret;
502  }
503 
505  {
506  MultiIterator ret = *this;
507  ret -= d;
508  return ret;
509  }
510 
512  {
513  return m_ptr [n];
514  }
515 
517  {
518  return m_ptr [d[level]];
519  }
520 
521  reference operator* () const
522  {
523  return *m_ptr;
524  }
525 
526  pointer get () const
527  {
528  return m_ptr;
529  }
530 
531  pointer operator->() const
532  {
533  return &(operator*());
534  }
535 
536  bool operator!= (const MultiIterator &rhs) const
537  {
538  return m_ptr != rhs.m_ptr;
539  }
540 
541  bool operator== (const MultiIterator &rhs) const
542  {
543  return m_ptr == rhs.m_ptr;
544  }
545 
546  bool operator< (const MultiIterator &rhs) const
547  {
548  return m_ptr < rhs.m_ptr;
549  }
550 
551  bool operator<= (const MultiIterator &rhs) const
552  {
553  return m_ptr <= rhs.m_ptr;
554  }
555 
556  bool operator> (const MultiIterator &rhs) const
557  {
558  return m_ptr > rhs.m_ptr;
559  }
560 
561  bool operator>= (const MultiIterator &rhs) const
562  {
563  return m_ptr >= rhs.m_ptr;
564  }
565 
566  iterator iteratorForDimension(unsigned int d) const
567  {
568  vigra_precondition(d == 0,
569  "MultiIterator<1>::iteratorForDimension(d): d == 0 required");
570  const difference_type stride = 1;
571  return iterator(m_ptr, &stride, 0);
572  }
573 
574  template <unsigned int K>
575  MultiIterator<K+1, T, REFERENCE, POINTER> &
576  dim()
577  {
578  return *this;
579  }
580 
581  MultiIterator<1, T, REFERENCE, POINTER> &
582  dim0() { return *this; }
583 
584  protected:
585 
587  total_stride(typename multi_difference_type::const_iterator d) const
588  {
589  return d[level];
590  }
591 };
592 
593 /********************************************************/
594 /* */
595 /* MultiIterator<2> */
596 /* */
597 /********************************************************/
598 
599 //
600 template <class T, class REFERENCE, class POINTER>
601 class MultiIterator<2, T, REFERENCE, POINTER>
602 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
603 : public MultiIterator<1, T, REFERENCE, POINTER>
604 #endif
605 {
606  public:
607 
608  typedef MultiIterator<1, T, REFERENCE, POINTER> base_type;
609  enum { level = 1 };
610  typedef T value_type;
611  typedef REFERENCE reference;
612  typedef const value_type &const_reference;
613  typedef POINTER pointer;
614  typedef const value_type *const_pointer;
615  typedef typename MultiArrayShape<2>::type multi_difference_type;
616  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
617  typedef typename stride_traits::stride_type difference_type;
618  typedef typename stride_traits::stride_array_type difference_array_type;
619  typedef typename stride_traits::shape_array_type shape_array_type;
620  typedef base_type next_type;
621  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
622  typedef multi_dimensional_traverser_tag iterator_category;
623 
624  protected:
625  difference_array_type m_stride;
626  shape_array_type m_shape;
627 
628  public:
629  /* use default copy constructor and assignment operator */
630 
631  MultiIterator ()
632  : base_type (),
633  m_stride (0), m_shape (0)
634  {}
635 
636  MultiIterator (pointer ptr,
637  const difference_array_type & stride,
638  const shape_array_type & shape)
639  : base_type (ptr, stride, shape),
640  m_stride (stride), m_shape (shape)
641  {}
642 
643  void operator++ ()
644  {
645  this->m_ptr += m_stride [level];
646  }
647 
648  void operator-- ()
649  {
650  this->m_ptr -= m_stride [level];
651  }
652 
654  {
655  MultiIterator ret = *this;
656  ++(*this);
657  return ret;
658  }
659 
661  {
662  MultiIterator ret = *this;
663  --(*this);
664  return ret;
665  }
666 
668  {
669  this->m_ptr += n * m_stride [level];
670  return *this;
671  }
672 
674  {
675  this->m_ptr += total_stride(d.begin());
676  return *this;
677  }
678 
680  {
681  this->m_ptr -= n * m_stride [level];
682  return *this;
683  }
684 
686  {
687  this->m_ptr -= total_stride(d.begin());
688  return *this;
689  }
690 
692  {
693  MultiIterator ret = *this;
694  ret += n;
695  return ret;
696  }
697 
699  {
700  MultiIterator ret = *this;
701  ret += d;
702  return ret;
703  }
704 
705  difference_type operator- (MultiIterator const & d) const
706  {
707  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
708  }
709 
711  {
712  MultiIterator ret = *this;
713  ret -= n;
714  return ret;
715  }
716 
718  {
719  MultiIterator ret = *this;
720  ret -= d;
721  return ret;
722  }
723 
725  {
726  return this->m_ptr [n*m_stride [level]];
727  }
728 
730  {
731  return this->m_ptr [total_stride(d.begin())];
732  }
733 
734  next_type begin () const
735  {
736  return *this;
737  }
738 
739  next_type end () const
740  {
741  next_type ret = *this;
742  ret += m_shape [level-1];
743  return ret;
744  }
745 
746  iterator iteratorForDimension(unsigned int d) const
747  {
748  vigra_precondition(d <= level,
749  "MultiIterator<N>::iteratorForDimension(d): d < N required");
750  return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
751  }
752 
753  template <unsigned int K>
754  MultiIterator<K+1, T, REFERENCE, POINTER> &
755  dim()
756  {
757  return *this;
758  }
759 
760  MultiIterator<1, T, REFERENCE, POINTER> &
761  dim0() { return *this; }
762  MultiIterator<2, T, REFERENCE, POINTER> &
763  dim1() { return *this; }
764 
765  protected:
766 
768  total_stride(typename multi_difference_type::const_iterator d) const
769  {
770  return d[level]*m_stride[level] + base_type::total_stride(d);
771  }
772 };
773 
774 /********************************************************/
775 /* */
776 /* MultiIterator<N> */
777 /* */
778 /********************************************************/
779 
780 /** \brief A multi-dimensional hierarchical iterator to be used with
781  \ref vigra::MultiArrayView if it is not strided.
782 
783  See \ref MultiIteratorPage for further documentation.
784 
785 <b>\#include</b> <vigra/multi_iterator.hxx>
786 
787 Namespace: vigra
788 */
789 template <unsigned int N, class T, class REFERENCE, class POINTER>
790 class MultiIterator
791 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
792 : public MultiIterator<N-1, T, REFERENCE, POINTER>
793 #endif
794 {
795 public:
796 
797  /** the type of the parent in the inheritance hierarchy.
798  */
799  typedef MultiIterator<N-1, T, REFERENCE, POINTER> base_type;
800 
801  /** the iterator's level in the dimension hierarchy
802  */
803  enum { level = N-1 };
804 
805  /** the iterator's value type
806  */
807  typedef T value_type;
808 
809  /** reference type (result of operator[])
810  */
811  typedef REFERENCE reference;
812 
813  /** const reference type (result of operator[] const)
814  */
815  typedef const value_type &const_reference;
816 
817  /** pointer type
818  */
819  typedef POINTER pointer;
820 
821  /** const pointer type
822  */
823  typedef const value_type *const_pointer;
824 
825  /** multi difference type
826  (used for offsetting along all axes simultaneously)
827  */
829 
830  /** difference type (used for offsetting)
831  */
832 #ifndef DOXYGEN
833  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
834  typedef typename stride_traits::stride_type difference_type;
835  typedef typename stride_traits::stride_array_type difference_array_type;
836  typedef typename stride_traits::shape_array_type shape_array_type;
837 #else
839 #endif
840 
841  /** the MultiIterator for the next lower dimension.
842  */
844 
845  /** the 1-dimensional iterator for this iterator hierarchy
846  (result of iteratorForDimension()).
847  */
849 
850  /** the iterator tag (image traverser)
851  */
852  typedef multi_dimensional_traverser_tag iterator_category;
853 
854  /* use default copy constructor and assignment operator */
855 
856  /** default constructor.
857  */
859  {}
860 
861  /** construct from pointer, strides (offset of a sample to the
862  next) for every dimension, and the shape.
863  */
865  const difference_array_type & stride,
866  const shape_array_type & shape)
867  : base_type (ptr, stride, shape)
868  {}
869 
870 
871  /** prefix-increment the iterator in its current dimension
872  */
873  void operator++ ()
874  {
875  this->m_ptr += this->m_stride [level];
876  }
877 
878  /** prefix-decrement the iterator in its current dimension
879  */
880  void operator-- ()
881  {
882  this->m_ptr -= this->m_stride [level];
883  }
884 
885  /** postfix-increment the iterator in its current dimension
886  */
888  {
889  MultiIterator ret = *this;
890  ++(*this);
891  return ret;
892  }
893 
894  /** postfix-decrement the iterator in its current dimension
895  */
897  {
898  MultiIterator ret = *this;
899  --(*this);
900  return ret;
901  }
902 
903  /** increment the iterator in its current dimension
904  by the given value.
905  */
907  {
908  this->m_ptr += n * this->m_stride [level];
909  return *this;
910  }
911 
912  /** increment the iterator in all dimensions
913  by the given offset.
914  */
916  {
917  this->m_ptr += total_stride(d.begin());
918  return *this;
919  }
920 
921  /** decrement the iterator in its current dimension
922  by the given value.
923  */
925  {
926  this->m_ptr -= n * this->m_stride [level];
927  return *this;
928  }
929 
930  /** decrement the iterator in all dimensions
931  by the given offset.
932  */
934  {
935  this->m_ptr -= total_stride(d.begin());
936  return *this;
937  }
938 
939  /** addition within current dimension
940  */
942  {
943  MultiIterator ret = *this;
944  ret += n;
945  return ret;
946  }
947 
948  /** addition along all dimensions
949  */
951  {
952  MultiIterator ret = *this;
953  ret += d;
954  return ret;
955  }
956 
957  /** difference of two iterators in the current dimension.
958  The result of this operation is undefined if the iterator
959  doesn't point to element 0 in all dimensions below its current dimension.
960  */
962  {
963  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
964  }
965 
966  /** subtraction within current dimension
967  */
969  {
970  MultiIterator ret = *this;
971  ret -= n;
972  return ret;
973  }
974 
975  /** subtraction along all dimensions
976  */
978  {
979  MultiIterator ret = *this;
980  ret -= d;
981  return ret;
982  }
983 
984 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
985  /** derefenrence item
986  */
987  reference operator* () const;
988 
989  /** get address of current item
990  */
991  pointer get () const;
992 
993  /** call method of current item
994  */
995  pointer operator->() const;
996 
997  /** inequality. True if iterators reference different items.
998  */
999  bool operator!= (const MultiIterator &rhs) const;
1000 
1001  /** equality. True if iterators reference the same items.
1002  */
1003  bool operator== (const MultiIterator &rhs) const;
1004 
1005  /** less than.
1006  */
1007  bool operator< (const MultiIterator &rhs) const;
1008 
1009  /** less or equal.
1010  */
1011  bool operator<= (const MultiIterator &rhs) const;
1012 
1013  /** greater than.
1014  */
1015  bool operator> (const MultiIterator &rhs) const;
1016 
1017  /** greater or equal.
1018  */
1019  bool operator>= (const MultiIterator &rhs) const;
1020 #endif
1021 
1022  /** access the array element at the given offset in
1023  the current dimension.
1024  */
1026  {
1027  return this->m_ptr [n* this->m_stride [level]];
1028  }
1029 
1030  /** access the array element at the given offset.
1031  */
1033  {
1034  return this->m_ptr [total_stride(d.begin())];
1035  }
1036 
1037  /** Return the (N-1)-dimensional multi-iterator that points to
1038  the first (N-1)-dimensional subarray of the
1039  N-dimensional array this iterator is referring to.
1040  The result is only valid if this iterator refers to location
1041  0 in <em>all</em> dimensions below its current dimension N,
1042  otherwise it is undefined. Usage:
1043 
1044  \code
1045 
1046  MultiIterator<2, int> outer = ...; // this iterator
1047 
1048  MultiIterator<2, int>::next_type inner = outer.begin();
1049  for(; inner != outer.end(); ++inner)
1050  {
1051  // manipulate current 1D subimage
1052  }
1053  \endcode
1054  */
1055  next_type begin () const
1056  {
1057  return *this;
1058  }
1059 
1060  /** Return the (N-1)-dimensional multi-iterator that points beyond
1061  the last (N-1)-dimensional subarray of the
1062  N-dimensional array this iterator is referring to.
1063  The result is only valid if this iterator refers to location
1064  0 in <em>all</em> dimensions below its current dimension N,
1065  otherwise it is undefined.
1066  */
1067  next_type end () const
1068  {
1069  next_type ret = *this;
1070  ret += this->m_shape [level-1];
1071  return ret;
1072  }
1073 
1074  /** Get a 1-dimensional, STL-compatible iterator for the
1075  given dimension, pointing to the current element of <TT>this</TT>.
1076  Usage:
1077 
1078  \code
1079 
1080  MultiIterator<3, int> outer = ...; // this iterator
1081 
1082  MultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
1083  MultiIterator<3, int>::iterator end = i + height;
1084  for(; i != end; ++i)
1085  {
1086  // go down the current column starting at the location of 'outer'
1087  }
1088  \endcode
1089  */
1090  iterator iteratorForDimension(unsigned int d) const
1091  {
1092  vigra_precondition(d <= level,
1093  "MultiIterator<N>::iteratorForDimension(d): d < N required");
1094  return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d),0);
1095  }
1096  /** Return the multi-iterator that operates on dimension K in order
1097  to manipulate this dimension directly. Usage:
1098 
1099  \code
1100 
1101  MultiIterator<3, int> i3 = ...;
1102 
1103  i3.template dim<2>()++; // increment outer dimension
1104  i3.template dim<0>()++; // increment inner dimension
1105  \endcode
1106 
1107  For convenience, the same functionality is also available
1108  as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
1109 
1110  \code
1111 
1112  MultiIterator<3, int> i3 = ...;
1113 
1114  i3.dim2()++; // increment outer dimension
1115  i3.dim0()++; // increment inner dimension
1116  \endcode
1117  */
1118  template <unsigned int K>
1121  {
1122  return *this;
1123  }
1124 
1126  dim0() { return *this; }
1127  MultiIterator<2, T, REFERENCE, POINTER> &
1128  dim1() { return *this; }
1129  MultiIterator<3, T, REFERENCE, POINTER> &
1130  dim2() { return *this; }
1131  MultiIterator<4, T, REFERENCE, POINTER> &
1132  dim3() { return *this; }
1133  MultiIterator<5, T, REFERENCE, POINTER> &
1134  dim4() { return *this; }
1135 
1136  protected:
1137 
1139  total_stride(typename multi_difference_type::const_iterator d) const
1140  {
1141  return d[level]*this->m_stride[level] + base_type::total_stride(d);
1142  }
1143 
1144 };
1145 
1146 /********************************************************/
1147 /* */
1148 /* StridedMultiIterator */
1149 /* */
1150 /********************************************************/
1151 
1152 template <unsigned int N, class T, class REFERENCE, class POINTER>
1153 class StridedMultiIterator;
1154 
1155 /********************************************************/
1156 /* */
1157 /* StridedMultiIterator<1> */
1158 /* */
1159 /********************************************************/
1160 
1161 //
1162 template <class T, class REFERENCE, class POINTER>
1163 class StridedMultiIterator<1, T, REFERENCE, POINTER>
1164 {
1165  public:
1166  enum { level = 0 };
1167  typedef T value_type;
1168  typedef REFERENCE reference;
1169  typedef const value_type &const_reference;
1170  typedef POINTER pointer;
1171  typedef const value_type *const_pointer;
1172  typedef typename MultiArrayShape<1>::type multi_difference_type;
1173  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1174  typedef typename stride_traits::stride_type difference_type;
1175  typedef typename stride_traits::stride_array_type difference_array_type;
1176  typedef typename stride_traits::shape_array_type shape_array_type;
1177  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1178  typedef std::random_access_iterator_tag iterator_category;
1179 
1180  protected:
1181  pointer m_ptr;
1182  difference_type m_stride;
1183 
1184  /* use default copy constructor and assignment operator */
1185 
1186  public:
1188  : m_ptr (0), m_stride (0)
1189  {}
1190 
1192  const difference_array_type & stride,
1193  const shape_array_type &)
1194  : m_ptr (ptr), m_stride (stride [level])
1195  {}
1196 
1197  void operator++ ()
1198  {
1199  m_ptr += m_stride;
1200  }
1201 
1202  void operator-- ()
1203  {
1204  m_ptr -= m_stride;
1205  }
1206 
1208  {
1209  StridedMultiIterator ret = *this;
1210  ++(*this);
1211  return ret;
1212  }
1213 
1215  {
1216  StridedMultiIterator ret = *this;
1217  --(*this);
1218  return ret;
1219  }
1220 
1222  {
1223  m_ptr += n * m_stride;
1224  return *this;
1225  }
1226 
1228  {
1229  m_ptr += d[level] * m_stride;
1230  return *this;
1231  }
1232 
1234  {
1235  m_ptr -= n * m_stride;
1236  return *this;
1237  }
1238 
1240  {
1241  m_ptr -= d[level] * m_stride;
1242  return *this;
1243  }
1244 
1246  {
1247  StridedMultiIterator ret = *this;
1248  ret += n;
1249  return ret;
1250  }
1251 
1253  {
1254  StridedMultiIterator ret = *this;
1255  ret += d;
1256  return ret;
1257  }
1258 
1260  {
1261  return (m_ptr - d.m_ptr) / m_stride;
1262  }
1263 
1265  {
1266  StridedMultiIterator ret = *this;
1267  ret -= n;
1268  return ret;
1269  }
1270 
1272  {
1273  StridedMultiIterator ret = *this;
1274  ret -= d;
1275  return ret;
1276  }
1277 
1279  {
1280  return m_ptr [n*m_stride];
1281  }
1282 
1284  {
1285  return m_ptr [d[level]*m_stride];
1286  }
1287 
1288  reference operator* () const
1289  {
1290  return *m_ptr;
1291  }
1292 
1293  pointer get () const
1294  {
1295  return m_ptr;
1296  }
1297 
1298  pointer operator->() const
1299  {
1300  return &(operator*());
1301  }
1302 
1303  bool operator!= (const StridedMultiIterator &rhs) const
1304  {
1305  return m_ptr != rhs.m_ptr;
1306  }
1307 
1308  bool operator== (const StridedMultiIterator &rhs) const
1309  {
1310  return m_ptr == rhs.m_ptr;
1311  }
1312 
1313  bool operator< (const StridedMultiIterator &rhs) const
1314  {
1315  return m_ptr < rhs.m_ptr;
1316  }
1317 
1318  bool operator<= (const StridedMultiIterator &rhs) const
1319  {
1320  return m_ptr <= rhs.m_ptr;
1321  }
1322 
1323  bool operator> (const StridedMultiIterator &rhs) const
1324  {
1325  return m_ptr > rhs.m_ptr;
1326  }
1327 
1328  bool operator>= (const StridedMultiIterator &rhs) const
1329  {
1330  return m_ptr >= rhs.m_ptr;
1331  }
1332 
1333  iterator iteratorForDimension(unsigned int d) const
1334  {
1335  vigra_precondition(d == 0,
1336  "StridedMultiIterator<1>::iteratorForDimension(d): d == 0 required");
1337  const difference_type stride = 1;
1338  return iterator(m_ptr, &stride, 0);
1339  }
1340 
1341  template <unsigned int K>
1342  StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1343  dim()
1344  {
1345  return *this;
1346  }
1347 
1348  StridedMultiIterator<1, T, REFERENCE, POINTER> &
1349  dim0() { return *this; }
1350 
1351  protected:
1352 
1354  total_stride(typename multi_difference_type::const_iterator d) const
1355  {
1356  return d[level] * m_stride;
1357  }
1358 };
1359 
1360 /********************************************************/
1361 /* */
1362 /* StridedMultiIterator<2> */
1363 /* */
1364 /********************************************************/
1365 
1366 //
1367 template <class T, class REFERENCE, class POINTER>
1368 class StridedMultiIterator<2, T, REFERENCE, POINTER>
1369 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1370 : public StridedMultiIterator<1, T, REFERENCE, POINTER>
1371 #endif
1372 {
1373  public:
1374 
1375  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
1376  enum { level = 1 };
1377  typedef T value_type;
1378  typedef REFERENCE reference;
1379  typedef const value_type &const_reference;
1380  typedef POINTER pointer;
1381  typedef const value_type *const_pointer;
1382  typedef typename MultiArrayShape<2>::type multi_difference_type;
1383  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1384  typedef typename stride_traits::stride_type difference_type;
1385  typedef typename stride_traits::stride_array_type difference_array_type;
1386  typedef typename stride_traits::shape_array_type shape_array_type;
1387  typedef base_type next_type;
1388  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1389  typedef multi_dimensional_traverser_tag iterator_category;
1390 
1391  protected:
1392  difference_array_type m_stride;
1393  shape_array_type m_shape;
1394 
1395  public:
1396  /* use default copy constructor and assignment operator */
1397 
1399  : base_type (),
1400  m_stride (0), m_shape (0)
1401  {}
1402 
1404  const difference_array_type & stride,
1405  const shape_array_type & shape)
1406  : base_type (ptr, stride, shape),
1407  m_stride (stride), m_shape (shape)
1408  {}
1409 
1410  void operator++ ()
1411  {
1412  this->m_ptr += m_stride [level];
1413  }
1414 
1415  void operator-- ()
1416  {
1417  this->m_ptr -= m_stride [level];
1418  }
1419 
1421  {
1422  StridedMultiIterator ret = *this;
1423  ++(*this);
1424  return ret;
1425  }
1426 
1428  {
1429  StridedMultiIterator ret = *this;
1430  --(*this);
1431  return ret;
1432  }
1433 
1435  {
1436  this->m_ptr += n * m_stride [level];
1437  return *this;
1438  }
1439 
1441  {
1442  this->m_ptr += total_stride(d.begin());
1443  return *this;
1444  }
1445 
1447  {
1448  this->m_ptr -= n * m_stride [level];
1449  return *this;
1450  }
1451 
1453  {
1454  this->m_ptr -= total_stride(d.begin());
1455  return *this;
1456  }
1457 
1459  {
1460  StridedMultiIterator ret = *this;
1461  ret += n;
1462  return ret;
1463  }
1464 
1466  {
1467  StridedMultiIterator ret = *this;
1468  ret += d;
1469  return ret;
1470  }
1471 
1473  {
1474  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1475  }
1476 
1478  {
1479  StridedMultiIterator ret = *this;
1480  ret -= n;
1481  return ret;
1482  }
1483 
1485  {
1486  StridedMultiIterator ret = *this;
1487  ret -= d;
1488  return ret;
1489  }
1490 
1492  {
1493  return this->m_ptr [n*m_stride [level]];
1494  }
1495 
1497  {
1498  return this->m_ptr [total_stride(d.begin())];
1499  }
1500 
1501  next_type begin () const
1502  {
1503  return *this;
1504  }
1505 
1506  next_type end () const
1507  {
1508  next_type ret = *this;
1509  ret += m_shape [level-1];
1510  return ret;
1511  }
1512 
1513  iterator iteratorForDimension(unsigned int d) const
1514  {
1515  vigra_precondition(d <= level,
1516  "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
1517  return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
1518  }
1519 
1520  template <unsigned int K>
1521  StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1522  dim()
1523  {
1524  return *this;
1525  }
1526 
1527  StridedMultiIterator<1, T, REFERENCE, POINTER> &
1528  dim0() { return *this; }
1529  StridedMultiIterator<2, T, REFERENCE, POINTER> &
1530  dim1() { return *this; }
1531 
1532  protected:
1533 
1535  total_stride(typename multi_difference_type::const_iterator d) const
1536  {
1537  return d[level]*m_stride[level] + base_type::total_stride(d);
1538  }
1539 };
1540 
1541 /********************************************************/
1542 /* */
1543 /* StridedMultiIterator<N> */
1544 /* */
1545 /********************************************************/
1546 
1547 /** \brief A multi-dimensional hierarchical iterator to be used with
1548  \ref vigra::MultiArrayView if it is not strided.
1549 
1550  See \ref MultiIteratorPage for further documentation.
1551 
1552 <b>\#include</b> <vigra/multi_iterator.hxx>
1553 
1554 Namespace: vigra
1555 */
1556 template <unsigned int N, class T, class REFERENCE, class POINTER>
1557 class StridedMultiIterator
1558 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1559 : public StridedMultiIterator<N-1, T, REFERENCE, POINTER>
1560 #endif
1561 {
1562 public:
1563 
1564  /** the type of the parent in the inheritance hierarchy.
1565  */
1566  typedef StridedMultiIterator<N-1, T, REFERENCE, POINTER> base_type;
1567 
1568  /** the iterator's level in the dimension hierarchy
1569  */
1570  enum { level = N-1 };
1571 
1572  /** the iterator's value type
1573  */
1574  typedef T value_type;
1575 
1576  /** reference type (result of operator[])
1577  */
1578  typedef REFERENCE reference;
1579 
1580  /** const reference type (result of operator[] const)
1581  */
1582  typedef const value_type &const_reference;
1583 
1584  /** pointer type
1585  */
1586  typedef POINTER pointer;
1587 
1588  /** const pointer type
1589  */
1590  typedef const value_type *const_pointer;
1591 
1592  /** multi difference type
1593  (used for offsetting along all axes simultaneously)
1594  */
1596 
1597  /** difference type (used for offsetting)
1598  */
1599 #ifndef DOXYGEN
1600  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1601  typedef typename stride_traits::stride_type difference_type;
1602  typedef typename stride_traits::stride_array_type difference_array_type;
1603 #else
1605 #endif
1606 
1607  /** the StridedMultiIterator for the next lower dimension.
1608  */
1610 
1611  /** the 1-dimensional iterator for this iterator hierarchy
1612  (result of iteratorForDimension()).
1613  */
1615 
1616  /** the iterator tag (image traverser)
1617  */
1618  typedef multi_dimensional_traverser_tag iterator_category;
1619 
1620  /* use default copy constructor and assignment operator */
1621 
1622  /** default constructor.
1623  */
1625  {}
1626 
1627  /** construct from pointer, strides (offset of a sample to the
1628  next) for every dimension, and the shape.
1629  */
1631  const difference_array_type & stride,
1632  const difference_array_type & shape)
1633  : base_type (ptr, stride, shape)
1634  {}
1635 
1636 
1637  /** prefix-increment the iterator in its current dimension
1638  */
1640  {
1641  this->m_ptr += this->m_stride [level];
1642  }
1643 
1644  /** prefix-decrement the iterator in its current dimension
1645  */
1647  {
1648  this->m_ptr -= this->m_stride [level];
1649  }
1650 
1651  /** postfix-increment the iterator in its current dimension
1652  */
1654  {
1655  StridedMultiIterator ret = *this;
1656  ++(*this);
1657  return ret;
1658  }
1659 
1660  /** postfix-decrement the iterator in its current dimension
1661  */
1663  {
1664  StridedMultiIterator ret = *this;
1665  --(*this);
1666  return ret;
1667  }
1668 
1669  /** increment the iterator in its current dimension
1670  by the given value.
1671  */
1673  {
1674  this->m_ptr += n * this->m_stride [level];
1675  return *this;
1676  }
1677 
1678  /** increment the iterator in all dimensions
1679  by the given offset.
1680  */
1682  {
1683  this->m_ptr += total_stride(d.begin());
1684  return *this;
1685  }
1686 
1687  /** decrement the iterator in its current dimension
1688  by the given value.
1689  */
1691  {
1692  this->m_ptr -= n * this->m_stride [level];
1693  return *this;
1694  }
1695 
1696  /** decrement the iterator in all dimensions
1697  by the given offset.
1698  */
1700  {
1701  this->m_ptr -= total_stride(d.begin());
1702  return *this;
1703  }
1704 
1705  /** addition within current dimension
1706  */
1708  {
1709  StridedMultiIterator ret = *this;
1710  ret += n;
1711  return ret;
1712  }
1713 
1714  /** addition along all dimensions
1715  */
1717  {
1718  StridedMultiIterator ret = *this;
1719  ret += d;
1720  return ret;
1721  }
1722 
1723  /** difference of two iterators in the current dimension.
1724  The result of this operation is undefined if the iterator
1725  doesn't point to element 0 in all dimensions below its current dimension.
1726  */
1728  {
1729  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1730  }
1731 
1732  /** subtraction within current dimension
1733  */
1735  {
1736  StridedMultiIterator ret = *this;
1737  ret -= n;
1738  return ret;
1739  }
1740 
1741  /** subtraction along all dimensions
1742  */
1744  {
1745  StridedMultiIterator ret = *this;
1746  ret -= d;
1747  return ret;
1748  }
1749 
1750 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
1751  /** derefenrence item
1752  */
1753  reference operator* () const;
1754 
1755  /** get address of current item
1756  */
1757  pointer get () const;
1758 
1759  /** call method of current item
1760  */
1761  pointer operator->() const;
1762 
1763  /** inequality. True if iterators reference different items.
1764  */
1765  bool operator!= (const StridedMultiIterator &rhs) const;
1766 
1767  /** equality. True if iterators reference the same items.
1768  */
1769  bool operator== (const StridedMultiIterator &rhs) const;
1770 
1771  /** less than.
1772  */
1773  bool operator< (const StridedMultiIterator &rhs) const;
1774 
1775  /** less or equal.
1776  */
1777  bool operator<= (const StridedMultiIterator &rhs) const;
1778 
1779  /** greater than.
1780  */
1781  bool operator> (const StridedMultiIterator &rhs) const;
1782 
1783  /** greater or equal.
1784  */
1785  bool operator>= (const StridedMultiIterator &rhs) const;
1786 #endif
1787 
1788  /** access the array element at the given offset in
1789  the current dimension.
1790  */
1792  {
1793  return this->m_ptr [n* this->m_stride [level]];
1794  }
1795 
1796  /** access the array element at the given offset.
1797  */
1799  {
1800  return this->m_ptr [total_stride(d.begin())];
1801  }
1802 
1803  /** Return the (N-1)-dimensional multi-iterator that points to
1804  the first (N-1)-dimensional subarray of the
1805  N-dimensional array this iterator is referring to.
1806  The result is only valid if this iterator refers to location
1807  0 in <em>all</em> dimensions below its current dimension N,
1808  otherwise it is undefined. Usage:
1809 
1810  \code
1811 
1812  StridedMultiIterator<2, int> outer = ...; // this iterator
1813 
1814  StridedMultiIterator<2, int>::next_type inner = outer.begin();
1815  for(; inner != outer.end(); ++inner)
1816  {
1817  // manipulate current 1D subimage
1818  }
1819  \endcode
1820  */
1821  next_type begin () const
1822  {
1823  return *this;
1824  }
1825 
1826  /** Return the (N-1)-dimensional multi-iterator that points beyond
1827  the last (N-1)-dimensional subarray of the
1828  N-dimensional array this iterator is referring to.
1829  The result is only valid if this iterator refers to location
1830  0 in <em>all</em> dimensions below its current dimension N,
1831  otherwise it is undefined.
1832  */
1833  next_type end () const
1834  {
1835  next_type ret = *this;
1836  ret += this->m_shape [level-1];
1837  return ret;
1838  }
1839 
1840  /** Get a 1-dimensional, STL-compatible iterator for the
1841  given dimension, pointing to the current element of <TT>this</TT>.
1842  Usage:
1843 
1844  \code
1845 
1846  StridedMultiIterator<3, int> outer = ...; // this iterator
1847 
1848  StridedMultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
1849  StridedMultiIterator<3, int>::iterator end = i + height;
1850  for(; i != end; ++i)
1851  {
1852  // go down the current column starting at the location of 'outer'
1853  }
1854  \endcode
1855  */
1856  iterator iteratorForDimension(unsigned int d) const
1857  {
1858  vigra_precondition(d <= level,
1859  "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
1860  return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d),0);
1861  }
1862  /** Return the multi-iterator that operates on dimension K in order
1863  to manipulate this dimension directly. Usage:
1864 
1865  \code
1866 
1867  StridedMultiIterator<3, int> i3 = ...;
1868 
1869  i3.template dim<2>()++; // increment outer dimension
1870  i3.template dim<0>()++; // increment inner dimension
1871  \endcode
1872 
1873  For convenience, the same functionality is also available
1874  as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
1875 
1876  \code
1877 
1878  StridedMultiIterator<3, int> i3 = ...;
1879 
1880  i3.dim2()++; // increment outer dimension
1881  i3.dim0()++; // increment inner dimension
1882  \endcode
1883  */
1884  template <unsigned int K>
1887  {
1888  return *this;
1889  }
1890 
1892  dim0() { return *this; }
1893  StridedMultiIterator<2, T, REFERENCE, POINTER> &
1894  dim1() { return *this; }
1895  StridedMultiIterator<3, T, REFERENCE, POINTER> &
1896  dim2() { return *this; }
1897  StridedMultiIterator<4, T, REFERENCE, POINTER> &
1898  dim3() { return *this; }
1899  StridedMultiIterator<5, T, REFERENCE, POINTER> &
1900  dim4() { return *this; }
1901 
1902  protected:
1903 
1905  total_stride(typename multi_difference_type::const_iterator d) const
1906  {
1907  return d[level]*this->m_stride[level] + base_type::total_stride(d);
1908  }
1909 
1910 };
1911 
1912 namespace detail {
1913 
1914 
1915 template <int K>
1916 struct CoordinateToScanOrder
1917 {
1918  template <int N>
1919  static MultiArrayIndex
1920  exec(const TinyVector <MultiArrayIndex, N> &shape,
1921  const TinyVector <MultiArrayIndex, N> & coordinate)
1922  {
1923  return coordinate[N-K] + shape[N-K] * CoordinateToScanOrder<K-1>::exec(shape, coordinate);
1924  }
1925 };
1926 
1927 template <>
1928 struct CoordinateToScanOrder<1>
1929 {
1930  template <int N>
1931  static MultiArrayIndex
1932  exec(const TinyVector <MultiArrayIndex, N> & /*shape*/,
1933  const TinyVector <MultiArrayIndex, N> & coordinate)
1934  {
1935  return coordinate[N-1];
1936  }
1937 };
1938 
1939 
1940 template <unsigned int M>
1941 struct MoveToScanOrderIndex
1942 {
1943  template <class Shape, class Ptr>
1944  static void
1945  exec(MultiArrayIndex newIndex, Shape const & shape,
1946  Shape & point, Ptr & p, Shape const & strides)
1947  {
1948  enum { N = Shape::static_size };
1949  MultiArrayIndex newPos = newIndex % shape[N-1-M];
1950  p += (newPos - point[N-1-M]) * strides[N-1-M];
1951  point[N-1-M] = newPos;
1952  MoveToScanOrderIndex<M-1>::exec(newIndex / shape[N-1-M], shape, point, p, strides);
1953  }
1954 
1955  template <class Shape, class Ptr1, class Ptr2>
1956  static void
1957  exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point,
1958  Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2)
1959  {
1960  enum { N = Shape::static_size };
1961  MultiArrayIndex newPos = newIndex % shape[N-1-M];
1962  p1 += (newPos - point[N-1-M]) * strides1[N-1-M];
1963  p2 += (newPos - point[N-1-M]) * strides2[N-1-M];
1964  point[N-1-M] = newPos;
1965  MoveToScanOrderIndex<M-1>::exec(newIndex / shape[N-1-M], shape, point,
1966  p1, strides1, p2, strides2);
1967  }
1968 };
1969 
1970 template <>
1971 struct MoveToScanOrderIndex<0>
1972 {
1973  template <class Shape, class Ptr>
1974  static void
1975  exec(MultiArrayIndex newIndex, Shape const & shape,
1976  Shape & point, Ptr & p, Shape const & strides)
1977  {
1978  enum { N = Shape::static_size };
1979  MultiArrayIndex newPos = std::min(newIndex, shape[N-1]);
1980  p += (newPos - point[N-1]) * strides[N-1];
1981  point[N-1] = newPos;
1982  }
1983 
1984  template <class Shape, class Ptr1, class Ptr2>
1985  static void
1986  exec(MultiArrayIndex newIndex, Shape const & shape, Shape & point,
1987  Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2)
1988  {
1989  enum { N = Shape::static_size };
1990  MultiArrayIndex newPos = std::min(newIndex, shape[N-1]);
1991  p1 += (newPos - point[N-1]) * strides1[N-1];
1992  p2 += (newPos - point[N-1]) * strides2[N-1];
1993  point[N-1] = newPos;
1994  }
1995 };
1996 
1997 #if 0 // alternative implementation, may be faster on some machines
1998 template <unsigned int M>
1999 struct MoveToScanOrderIndex
2000 {
2001  template <class Shape, class Ptr>
2002  static void
2003  exec(MultiArrayIndex & newIndex, Shape const & shape,
2004  Shape & point, Ptr & p, Shape const & strides, MultiArrayIndex shapeStride = 1)
2005  {
2006  enum { N = Shape::static_size };
2007  MoveToScanOrderIndex<M-1>::exec(newIndex, shape, point, p, strides, shapeStride*shape[N-1-M]);
2008  MultiArrayIndex newPos = newIndex / shapeStride;
2009  p += (newPos - point[N-1-M]) * strides[N-1-M];
2010  point[N-1-M] = newPos;
2011  newIndex %= shapeStride;
2012  }
2013 
2014  template <class Shape, class Ptr1, class Ptr2>
2015  static void
2016  exec(MultiArrayIndex & newIndex, Shape const & shape, Shape & point,
2017  Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2,
2018  MultiArrayIndex shapeStride = 1)
2019  {
2020  enum { N = Shape::static_size };
2021  MoveToScanOrderIndex<M-1>::exec(newIndex, shape, point,
2022  p1, strides1, p2, strides2, shapeStride*shape[N-1-M]);
2023  MultiArrayIndex newPos = newIndex / shapeStride;
2024  p1 += (newPos - point[N-1-M]) * strides1[N-1-M];
2025  p2 += (newPos - point[N-1-M]) * strides2[N-1-M];
2026  point[N-1-M] = newPos;
2027  newIndex %= shapeStride;
2028  }
2029 };
2030 
2031 template <>
2032 struct MoveToScanOrderIndex<0>
2033 {
2034  template <class Shape, class Ptr>
2035  static void
2036  exec(MultiArrayIndex & newIndex, Shape const & shape,
2037  Shape & point, Ptr & p, Shape const & strides, MultiArrayIndex shapeStride)
2038  {
2039  enum { N = Shape::static_size };
2040  MultiArrayIndex newPos = newIndex / shapeStride;
2041  p += (newPos - point[N-1]) * strides[N-1];
2042  point[N-1] = newPos;
2043  newIndex %= shapeStride;
2044  }
2045 
2046  template <class Shape, class Ptr1, class Ptr2>
2047  static void
2048  exec(MultiArrayIndex & newIndex, Shape const & shape, Shape & point,
2049  Ptr1 & p1, Shape const & strides1, Ptr2 & p2, Shape const & strides2,
2050  MultiArrayIndex shapeStride)
2051  {
2052  enum { N = Shape::static_size };
2053  MultiArrayIndex newPos = newIndex / shapeStride;
2054  p1 += (newPos - point[N-1]) * strides1[N-1];
2055  p2 += (newPos - point[N-1]) * strides2[N-1];
2056  point[N-1] = newPos;
2057  newIndex %= shapeStride;
2058  }
2059 };
2060 #endif
2061 
2062 }
2063 
2064  /** \brief Sequential iterator for MultiArrayView.
2065 
2066  This iterator provides STL-compatible random access iterator functionality for arbitrary
2067  \ref MultiArrayView instances, regardless of their shapes and strides. The
2068  class uses an implementation that minimizes speed penalties that could result from
2069  non-trivial strides. The <i>scan-order</i> is defined such that dimensions are iterated
2070  from front to back (first to last).
2071 
2072  You normally construct instances of this class by calling \ref MultiArrayView::begin()
2073  and \ref MultiArrayView::end().
2074 
2075  The iterator supports all functions listed in the STL documentation for
2076  <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
2077  */
2078 template <unsigned int N, class T, class REFERENCE, class POINTER, unsigned int M = N>
2080 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
2081 : protected StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1>
2082 #endif
2083 {
2084  typedef StridedScanOrderIterator<N, T, REFERENCE, POINTER, M-1> base_type;
2085  enum { level = M-1 };
2086 
2087  public:
2088 
2089  typedef typename base_type::value_type value_type;
2090  typedef typename base_type::pointer pointer;
2091  typedef typename base_type::reference reference;
2092  typedef typename base_type::const_reference const_reference;
2093  typedef typename base_type::shape_type shape_type;
2094  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
2095  typedef typename stride_traits::stride_type difference_type;
2096  typedef typename stride_traits::stride_array_type difference_array_type;
2098  typedef std::random_access_iterator_tag iterator_category;
2099 
2101  {}
2102 
2103  StridedScanOrderIterator(pointer i,
2104  shape_type const & shape, shape_type const & strides)
2105  : base_type(i, shape, strides)
2106  {}
2107 
2108  StridedScanOrderIterator & operator++()
2109  {
2110  base_type::operator++();
2111  if(this->point_[level-1] == this->shape_[level-1])
2112  {
2113  base_type::reset();
2114  this->i_ += this->strides_[level];
2115  ++this->point_[level];
2116  }
2117  return *this;
2118  }
2119 
2120  StridedScanOrderIterator operator++(int)
2121  {
2122  StridedScanOrderIterator res(*this);
2123  ++*this;
2124  return res;
2125  }
2126 
2128  {
2129  this->moveToScanOrderIndex(this->index_+i);
2130  return *this;
2131  }
2132 
2133  //! overload to add a coord-tuple:
2134  // it should be cheaper because the modulo-divisions are avoided
2135  StridedScanOrderIterator & operator+=(const shape_type &coordOffset)
2136  {
2137  this->moveRelative(dot(coordOffset,this->strides_),
2138  detail::CoordinateToScanOrder<N>::exec(this->shape_, coordOffset),
2139  coordOffset);
2140  return *this;
2141  }
2142  StridedScanOrderIterator & operator-=(const shape_type &coordOffset)
2143  {
2144  return operator+=(-coordOffset);
2145  }
2146 
2147  StridedScanOrderIterator & operator--()
2148  {
2149  base_type::operator--();
2150  if(this->point_[level-1] == -1)
2151  {
2152  base_type::inverseReset();
2153  this->i_ -= this->strides_[level];
2154  --this->point_[level];
2155  }
2156  return *this;
2157  }
2158 
2159  StridedScanOrderIterator operator--(int)
2160  {
2161  StridedScanOrderIterator res(*this);
2162  --*this;
2163  return res;
2164  }
2165 
2166  StridedScanOrderIterator & operator-=(MultiArrayIndex i)
2167  {
2168  return operator+=(-i);
2169  }
2170 
2171  StridedScanOrderIterator getEndIterator() const
2172  {
2173  StridedScanOrderIterator res(*this);
2174  res.moveToScanOrderIndex(prod(this->shape_));
2175  return res;
2176  }
2177 
2178  bool atBorder() const
2179  {
2180  return base_type::atBorder() ||
2181  this->point_[level] == 0 ||
2182  this->point_[level] == this->shape_[level] - 1;
2183  }
2184 
2185  unsigned int neighborhoodType() const
2186  {
2187  unsigned int res = base_type::neighborhoodType();
2188  if(this->point_[level] == 0)
2189  res |= (1 << 2*level);
2190  if(this->point_[level] == this->shape_[level]-1)
2191  res |= (2 << 2*level);
2192  return res;
2193  }
2194 
2195  StridedScanOrderIterator operator+(MultiArrayIndex d) const
2196  {
2197  return StridedScanOrderIterator(*this) += d;
2198  }
2199 
2200  StridedScanOrderIterator operator-(MultiArrayIndex d) const
2201  {
2202  return StridedScanOrderIterator(*this) -= d;
2203  }
2204 
2205 
2206  StridedScanOrderIterator operator+(const shape_type &coordOffset) const
2207  {
2208  return StridedScanOrderIterator(*this) += coordOffset;
2209  }
2210 
2211  StridedScanOrderIterator operator-(const shape_type &coordOffset) const
2212  {
2213  return StridedScanOrderIterator(*this) -= coordOffset;
2214  }
2215 
2216 
2217 
2218  MultiArrayIndex operator-(StridedScanOrderIterator const & r) const
2219  {
2220  return base_type::operator-(r);
2221  }
2222 
2223  bool operator==(StridedScanOrderIterator const & r)
2224  {
2225  return base_type::operator==(r);
2226  }
2227 
2228  bool operator!=(StridedScanOrderIterator const & r) const
2229  {
2230  return base_type::operator!=(r);
2231  }
2232 
2233  bool operator<(StridedScanOrderIterator const & r) const
2234  {
2235  return base_type::operator<(r);
2236  }
2237 
2238  bool operator<=(StridedScanOrderIterator const & r) const
2239  {
2240  return base_type::operator<=(r);
2241  }
2242 
2243  bool operator>(StridedScanOrderIterator const & r) const
2244  {
2245  return base_type::operator>(r);
2246  }
2247 
2248  bool operator>=(StridedScanOrderIterator const & r) const
2249  {
2250  return base_type::operator>=(r);
2251  }
2252 
2253  using base_type::point;
2254  using base_type::shape;
2255  using base_type::strides;
2256  using base_type::ptr;
2257  using base_type::index;
2258  using base_type::operator*;
2259  using base_type::operator->;
2260  using base_type::operator[];
2261 
2262  protected:
2263  void reset()
2264  {
2265  this->i_ -= this->shape_[level]*this->strides_[level];
2266  this->point_[level] = 0;
2267  }
2268 
2269  void inverseReset()
2270  {
2271  this->i_ += this->shape_[level]*this->strides_[level];
2272  this->point_[level] = this->shape_[level]-1;
2273  }
2274 
2275  template <class Ptr>
2276  void increment(Ptr & p2, shape_type const & strides2)
2277  {
2278  base_type::increment(p2, strides2);
2279  if(this->point_[level-1] == this->shape_[level-1])
2280  {
2281  base_type::reset();
2282  this->i_ += this->strides_[level];
2283  p2 += strides2[level] - this->shape_[level-1]*strides2[level-1];
2284  ++this->point_[level];
2285  }
2286  }
2287 
2288  template <class Ptr>
2289  void decrement(Ptr & p2, shape_type const & strides2)
2290  {
2291  base_type::decrement(p2, strides2);
2292  if(this->point_[level-1] == -1)
2293  {
2294  base_type::inverseReset();
2295  this->i_ -= this->strides_[level];
2296  p2 -= strides2[level] - this->shape_[level-1]*strides2[level-1];
2297  --this->point_[level];
2298  }
2299  }
2300  StridedScanOrderIterator & moveRelative(const MultiArrayIndex &pointerOffset,
2301  const MultiArrayIndex &indexOffset,
2302  const shape_type &coordOffset)
2303  {
2304  base_type::moveRelative(pointerOffset, indexOffset, coordOffset);
2305  this->point_[level] += coordOffset[level];
2306  return *this;
2307  }
2308 };
2309 
2310 template <unsigned int N, class T, class REFERENCE, class POINTER>
2311 class StridedScanOrderIterator<N, T, REFERENCE, POINTER, 1>
2312 {
2313  enum { level = 0 };
2314 
2315  public:
2316 
2317  typedef T value_type;
2318  typedef POINTER pointer;
2319  typedef T const * const_pointer;
2320  typedef REFERENCE reference;
2321  typedef T const & const_reference;
2322  typedef typename MultiArrayShape<N>::type shape_type;
2323  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
2324  typedef typename stride_traits::stride_type difference_type;
2325  typedef typename stride_traits::stride_array_type difference_array_type;
2326  typedef StridedScanOrderIterator iterator;
2327  typedef std::random_access_iterator_tag iterator_category;
2328 
2329  StridedScanOrderIterator()
2330  : i_((pointer)0),
2331  index_(0)
2332  {}
2333 
2334  StridedScanOrderIterator(pointer i,
2335  shape_type const & shape, shape_type const & strides)
2336  : i_(i),
2337  shape_(shape),
2338  strides_(strides),
2339  index_(0)
2340  {}
2341 
2342  StridedScanOrderIterator & operator++()
2343  {
2344  i_ += strides_[level];
2345  ++point_[level];
2346  ++index_;
2347  return *this;
2348  }
2349 
2350  StridedScanOrderIterator operator++(int)
2351  {
2352  StridedScanOrderIterator res(*this);
2353  ++*this;
2354  return res;
2355  }
2356 
2357  StridedScanOrderIterator & operator+=(MultiArrayIndex i)
2358  {
2359  this->moveToScanOrderIndex(index_+i);
2360  return *this;
2361  }
2362 
2363  //! overload to add a coord-tuple:
2364  StridedScanOrderIterator & operator+=(const shape_type &coordOffset)
2365  {
2366  this->moveRelative(dot(coordOffset,strides_),
2367  detail::CoordinateToScanOrder<N>::exec(shape_, coordOffset),
2368  coordOffset);
2369  return *this;
2370  }
2371 
2372  StridedScanOrderIterator & operator-=(const shape_type &coordOffset)
2373  {
2374  return operator+=(-coordOffset);
2375  }
2376 
2377  StridedScanOrderIterator & operator--()
2378  {
2379  i_ -= strides_[level];
2380  --point_[level];
2381  --index_;
2382  return *this;
2383  }
2384 
2385  StridedScanOrderIterator operator--(int)
2386  {
2387  StridedScanOrderIterator res(*this);
2388  --this;
2389  return res;
2390  }
2391 
2392  StridedScanOrderIterator & operator-=(MultiArrayIndex i)
2393  {
2394  return operator+=(-i);
2395  }
2396 
2397  reference operator*()
2398  {
2399  return *i_;
2400  }
2401 
2402  const_reference operator*() const
2403  {
2404  return *i_;
2405  }
2406 
2407  pointer operator->()
2408  {
2409  return i_;
2410  }
2411 
2412  const_pointer operator->() const
2413  {
2414  return i_;
2415  }
2416 
2417  pointer ptr()
2418  {
2419  return i_;
2420  }
2421 
2422  const_pointer ptr() const
2423  {
2424  return i_;
2425  }
2426 
2427  reference operator[](MultiArrayIndex i)
2428  {
2429  StridedScanOrderIterator t(*this);
2430  t.moveToScanOrderIndex(index_+i);
2431  return *t;
2432  }
2433 
2434  const_reference operator[](MultiArrayIndex i) const
2435  {
2436  StridedScanOrderIterator t(*this);
2437  t.moveToScanOrderIndex(index_+i);
2438  return *t;
2439  }
2440 
2441  StridedScanOrderIterator
2442  operator+(MultiArrayIndex d) const
2443  {
2444  return StridedScanOrderIterator(*this) += d;
2445  }
2446 
2447  StridedScanOrderIterator
2448  operator-(MultiArrayIndex d) const
2449  {
2450  return StridedScanOrderIterator(*this) -= d;
2451  }
2452 
2453  StridedScanOrderIterator operator+(const shape_type &coordOffset) const
2454  {
2455  return StridedScanOrderIterator(*this) += coordOffset;
2456  }
2457 
2458  StridedScanOrderIterator operator-(const shape_type &coordOffset) const
2459  {
2460  return StridedScanOrderIterator(*this) -= coordOffset;
2461  }
2462 
2464  operator-(StridedScanOrderIterator const & r) const
2465  {
2466  return index() - r.index();
2467  }
2468 
2469  bool
2470  operator==(StridedScanOrderIterator const & r)
2471  {
2472  return index() == r.index();
2473  }
2474 
2475  bool
2476  operator!=(StridedScanOrderIterator const & r) const
2477  {
2478  return index() != r.index();
2479  }
2480 
2481  bool
2482  operator<(StridedScanOrderIterator const & r) const
2483  {
2484  return index() < r.index();
2485  }
2486 
2487  bool
2488  operator<=(StridedScanOrderIterator const & r) const
2489  {
2490  return index() <= r.index();
2491  }
2492 
2493  bool
2494  operator>(StridedScanOrderIterator const & r) const
2495  {
2496  return index() > r.index();
2497  }
2498 
2499  bool
2500  operator>=(StridedScanOrderIterator const & r) const
2501  {
2502  return index() >= r.index();
2503  }
2504 
2505 
2506  bool atBorder() const
2507  {
2508  return point_[level] == 0 || point_[level] == shape_[level] - 1;
2509  }
2510 
2511  MultiArrayIndex index() const
2512  {
2513  return index_;
2514  }
2515 
2516  shape_type const & point() const
2517  {
2518  return point_;
2519  }
2520 
2521  shape_type const & shape() const
2522  {
2523  return shape_;
2524  }
2525 
2526  shape_type const & strides() const
2527  {
2528  return strides_;
2529  }
2530 
2531  StridedScanOrderIterator getEndIterator() const
2532  {
2533  StridedScanOrderIterator res(*this);
2534  res.moveToScanOrderIndex(prod(shape_));
2535  return res;
2536  }
2537 
2538  unsigned int neighborhoodType() const
2539  {
2540  unsigned int res = 0;
2541  if(this->point_[level] == 0)
2542  res |= 1;
2543  if(this->point_[level] == this->shape_[level]-1)
2544  res |= 2;
2545  return res;
2546  }
2547 
2548  protected:
2549  void reset()
2550  {
2551  i_ -= shape_[level]*strides_[level];
2552  point_[level] = 0;
2553  }
2554 
2555  void inverseReset()
2556  {
2557  i_ += shape_[level]*strides_[level];
2558  point_[level] = shape_[level] - 1;
2559  }
2560 
2561  void moveToScanOrderIndex(MultiArrayIndex newIndex)
2562  {
2563  index_ = newIndex;
2564  detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i_, strides_);
2565  }
2566 
2567  template <class Ptr>
2568  void increment(Ptr & p2, shape_type const & strides2)
2569  {
2570  operator++();
2571  p2 += strides2[level];
2572  }
2573 
2574  template <class Ptr>
2575  void decrement(Ptr & p2, shape_type const & strides2)
2576  {
2577  operator--();
2578  p2 -= strides2[level];
2579  }
2580 
2581  template <class Ptr>
2582  void moveToScanOrderIndex(MultiArrayIndex newIndex, Ptr & p2, shape_type const & strides2)
2583  {
2584  index_ = newIndex;
2585  detail::MoveToScanOrderIndex<N-1>::exec(newIndex, shape_, point_, i_, strides_, p2, strides2);
2586  }
2587 
2588  StridedScanOrderIterator & moveRelative(const MultiArrayIndex &pointerOffset,
2589  const MultiArrayIndex &indexOffset,
2590  const shape_type &coordOffset)
2591  {
2592  point_[level] += coordOffset[level];
2593 
2594  index_+= indexOffset;
2595  i_ += pointerOffset;
2596 
2597  return *this;
2598  }
2599 
2600  pointer i_;
2601  shape_type point_, shape_, strides_;
2602  MultiArrayIndex index_;
2603 };
2604 
2605 
2606 //@}
2607 
2608 } // namespace vigra
2609 
2610 #endif // VIGRA_MULTI_ITERATOR_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Wed Feb 27 2013)