[ 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 </UL>
67 </p>
68 
69 <p>
70  The Multidimensional Iterator concept allows navigation on arrays
71  of arbitrary dimension. It provides two modes of iteration:
72  <em>direct traveral</em>, and <em>hierarchical traversal</em>.
73  In general, hierarchical traversal will be faster, while only
74  direct traversal allows for true random access in all dimensions.
75  Via the <tt>dim<K>()</tt> function, operations applying to a particular
76  dimension can be used in the direct traversal mode. In contrast,
77  direct traversal functions should not be used in the hierarchical mode
78  because the hierarchical functions are only well-defined if the
79  iterator points to element 0 in all dimensions below its current dimension.
80  The current dimension of a <tt>MultiIterator<N, ...></tt> is <tt>N-1</tt>.
81 </p>
82 <h3>Gerneral Requirements for MultiIterator</h3>
83 <p>
84 <table border=2 cellspacing=0 cellpadding=2 width="100%">
85 <tr><th colspan=2>
86  Local Types
87  </th><th>
88  Meaning
89  </th>
90 </tr>
91 <tr><td colspan=2>
92  <tt>MultiIterator::value_type</tt></td><td>the underlying arrays's pixel type</td>
93 </tr>
94 <tr><td colspan=2>
95  <tt>MultiIterator::reference</tt></td>
96  <td>the iterator's reference type (return type of <TT>*iter</TT>). Will be
97  <tt>value_type &</tt> for a mutable iterator, and convertible to
98  <tt>value_type const &</tt> for a const iterator.</td>
99 </tr>
100 <tr><td colspan=2>
101  <tt>MultiIterator::pointer</tt></td>
102  <td>the iterator's pointer type (return type of <TT>iter.operator->()</TT>). Will be
103  <tt>value_type *</tt> for a mutable iterator, and convertible to
104  <tt>value_type const *</tt> for a const iterator.</td>
105 </tr>
106 <tr><td colspan=2>
107  <tt>MultiIterator::iterator_category</tt></td>
108  <td>the iterator tag (<tt>vigra::multi_dimensional_traverser_tag</tt>)</td>
109 </tr>
110 <tr><th>
111  Operation
112  </th><th>
113  Result
114  </th><th>
115  Semantics
116  </th>
117 </tr>
118 <tr><td colspan=2>
119  <tt>MultiIterator k;</tt></td><td>default constructor</td>
120 </tr>
121 <tr><td colspan=2>
122  <tt>MultiIterator k(i);</tt></td><td>copy constructor</td>
123 </tr>
124 <tr>
125  <td><tt>k = i</tt></td>
126  <td><tt>MultiIterator &</tt></td><td>assignment</td>
127 </tr>
128 <tr>
129  <td><tt>i == j</tt></td><td><tt>bool</tt></td>
130  <td>equality (iterators point to the same element)</td>
131 </tr>
132 <tr>
133  <td><tt>i != j</tt></td><td><tt>bool</tt></td>
134  <td>inequality (iterators don't point to the same element)</td>
135 </tr>
136 <tr>
137  <td><tt>*i</tt></td><td><tt>MultiIterator::reference</tt></td>
138  <td>access the current element</td>
139 </tr>
140 <tr>
141  <td><tt>i->member()</tt></td><td>depends on operation</td>
142  <td>call member function of underlying pixel type via <tt>operator-></tt> of iterator</td>
143 </tr>
144 </table>
145 </p>
146 <h3>Requirements for Direct Traversal</h3>
147 <p>
148 <table border=2 cellspacing=0 cellpadding=2 width="100%">
149 <tr><th colspan=2>
150  Local Types
151  </th><th>
152  Meaning
153  </th>
154 </tr>
155 <tr><td colspan=2>
156  <tt>MultiIterator::multi_difference_type</tt></td>
157  <td>the iterator's multi-dimensional difference type (<TT>TinyVector<MultiArrayIndex, N></TT>)</td>
158 </tr>
159 <tr><th>
160  Operation
161  </th><th>
162  Result
163  </th><th>
164  Semantics
165  </th>
166 </tr>
167 <tr>
168  <td><tt>i += diff</tt></td><td><tt>MultiIterator &</tt></td>
169  <td>add offset to current position</td>
170 </tr>
171 <tr>
172  <td><tt>i -= diff</tt></td><td><tt>MultiIterator &</tt></td>
173  <td>subtract offset from current position</td>
174 </tr>
175 <tr>
176  <td><tt>i + diff</tt></td><td><tt>MultiIterator</tt></td>
177  <td>create traverser by adding offset</td>
178 </tr>
179 <tr>
180  <td><tt>i - diff</tt></td><td><tt>MultiIterator</tt></td>
181  <td>create traverser by subtracting offset</td>
182 </tr>
183 <tr>
184  <td><tt>i[diff]</tt></td><td><tt>MultiIterator::reference</tt></td>
185  <td>access element at offset <tt>diff</tt></td>
186 </tr>
187 <tr>
188  <td><tt>i.dim<K>()</tt></td><td><tt>MultiIterator<K+1, T, ...></tt></td>
189  <td>Access the traverser with the current dimension set to K. Typically used to call
190  navigation functions referring to a particular dimension.<br>
191  Example (assuming <tt>i, j</tt> are 3-dimensional):<br>
192  \code
193  i.dim<0>()++; // increment dimension 0
194  i.dim<1>()++; // increment dimension 1
195  i.dim<2>()++; // increment dimension 2
196 
197  j += MultiIterator::multi_difference_type(1,1,1); // same effect
198  \endcode
199  </td>
200 </tr>
201 <tr><td colspan=3>
202  <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
203  <tt>diff</tt> is of type <tt>MultiIterator::multi_difference_type</tt><br>
204  <tt>K</tt> is an integer compile-time constant
205  </td>
206 </tr>
207 </table>
208 </p>
209 <p>
210 Note that it is impossible to support an <tt>operator-</tt> between two iterators which returns
211 a <tt>MultiIterator::multi_difference_type</tt> because it is impossible to decide to which
212 dimension a difference applies. Consider for example, a 2-dimensional iterator <tt>i</tt>, and
213 let <tt>j = i + multi_difference_type(width, 0)</tt>, <tt>k = i + multi_difference_type(0,1)</tt>,
214 where <tt>width</tt> is the array's total width. In general, <tt>j</tt> and <tt>k</tt> point to
215 the same memory location, so that the two cases cannot easily be distinguished (it is possible,
216 but iterator performance will suffer significantly, as is experienced with
217 \ref vigra::ImageIterator where differencing is allowed).
218 </p>
219 
220 <h3>Requirements for Hierarchical Traversal</h3>
221 <p>
222 <table border=2 cellspacing=0 cellpadding=2 width="100%">
223 <tr><th colspan=2>
224  Local Types
225  </th><th>
226  Meaning
227  </th>
228 </tr>
229 <tr><td colspan=2>
230  <tt>MultiIterator::difference_type</tt></td>
231  <td>the iterator's difference type (<TT>MultiArrayIndex</TT>)</td>
232 </tr>
233 <tr><td colspan=2>
234  <tt>MultiIterator::next_type</tt></td><td>type of the next iterator
235  (referring to the next lower dimension) in the hierarchy</td>
236 </tr>
237 <tr><th>
238  Operation
239  </th><th>
240  Result
241  </th><th>
242  Semantics
243  </th>
244 </tr>
245 <tr>
246  <td><tt>++i</tt></td><td><tt>MultiIterator &</tt></td>
247  <td>pre-increment iterator in its current dimension</td>
248 </tr>
249 <tr>
250  <td><tt>i++</tt></td><td><tt>MultiIterator</tt></td>
251  <td>post-increment iterator in its current dimension</td>
252 </tr>
253 <tr>
254  <td><tt>--i</tt></td><td><tt>MultiIterator &</tt></td>
255  <td>pre-decrement iterator in its current dimension</td>
256 </tr>
257 <tr>
258  <td><tt>i--</tt></td><td><tt>MultiIterator</tt></td>
259  <td>post-decrement iterator in its current dimension</td>
260 </tr>
261 <tr>
262  <td><tt>i += d</tt></td><td><tt>MultiIterator &</tt></td>
263  <td>add <tt>d</tt> in current dimension</td>
264 </tr>
265 <tr>
266  <td><tt>i -= d</tt></td><td><tt>MultiIterator &</tt></td>
267  <td>subtract <tt>d</tt> in from dimension</td>
268 </tr>
269 <tr>
270  <td><tt>i + d</tt></td><td><tt>MultiIterator</tt></td>
271  <td>create new iterator by adding <tt>d</tt> in current dimension</td>
272 </tr>
273 <tr>
274  <td><tt>i - d</tt></td><td><tt>MultiIterator</tt></td>
275  <td>create new iterator by subtracting <tt>d</tt> in current dimension</td>
276 </tr>
277 <tr>
278  <td><tt>i - j</tt></td><td><tt>difference_type</tt></td>
279  <td>difference of <tt>i</tt> and <tt>j</tt> in the current dimension<br>
280  <em>Note:</em> The result of this operation is undefined if the iterator
281  doesn't point to element 0 in all dimensions below its current dimension.</td>
282 </tr>
283 <tr>
284  <td><tt>i < j</tt></td><td><tt>bool</tt></td>
285  <td><tt>i - j < 0</tt><br>
286  <em>Note:</em> The result of this operation is undefined if the iterator
287  doesn't point to element 0 in all dimensions below its current dimension.</td>
288 </tr>
289 <tr>
290  <td><tt>i[d]</tt></td><td><tt>MultiIterator::reference</tt></td>
291  <td>access element by adding offset <tt>d</tt> in current dimension</td>
292 </tr>
293 <tr>
294  <td><tt>i.begin()</tt></td><td><tt>next_type</tt></td>
295  <td>create the hierarchical iterator poiting to the first element in the
296  next lower dimension.<br>
297  <em>Note:</em> The result of this operation is undefined if the iterator
298  doesn't point to element 0 in all dimensions below its current dimension.<br>
299  Usage:<br>
300  \code
301  MultiIterator<3, int> i3 = ..., end3 = ...;
302  for(; i3 != end3; ++i3)
303  {
304  MultiIterator<3, int>::next_type i2 = i3.begin(), end2 = i3.end();
305  for(; i2 != end2; ++i2)
306  {
307  MultiIterator<3, int>::next_type::next_type i1 = i2.begin(), end1 = i2.end();
308  for(; i1 != end1; ++i1)
309  {
310  ... // do something with the current element
311  }
312  }
313  }
314 
315  \endcode
316  </td>
317 </tr>
318 <tr>
319  <td><tt>i.end()</tt></td><td><tt>next_type</tt></td>
320  <td>create the hierarchical iterator poiting to the past-the-end location in the
321  next lower dimension.<br>
322  <em>Note:</em> The result of this operation is undefined if the iterator
323  doesn't point to element 0 in all dimensions below its current dimension.</td>
324 </tr>
325 <tr><td colspan=3>
326  <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
327  <tt>d</tt> is of type <tt>MultiIterator::difference_type</tt>
328  </td>
329 </tr>
330 </table>
331 </p>
332 
333 */
334 
335 /** \addtogroup MultiIteratorGroup Multi-dimensional Array Iterators
336 
337  \brief General iterators for arrays of arbitrary dimension.
338 */
339 //@{
340 
341  /** Index type for a single dimension of a MultiArrayView or
342  MultiArray.
343  */
344 typedef std::ptrdiff_t MultiArrayIndex;
345 
346  /** Traits class for the difference type of all MultiIterator, MultiArrayView, and
347  MultiArray variants.
348  */
349 template <unsigned int N>
351 {
352  public:
353  /** The difference type of all MultiIterator, MultiArrayView, and
354  MultiArray variants.
355  */
357 };
358 
359 /********************************************************/
360 /* */
361 /* MultiIterator */
362 /* */
363 /********************************************************/
364 
365 template <unsigned int N, class T, class REFERENCE, class POINTER>
366 class MultiIterator;
367 
368 /********************************************************/
369 /* */
370 /* MultiIterator<1> */
371 /* */
372 /********************************************************/
373 
374 //
375 template <class T, class REFERENCE, class POINTER>
376 class MultiIterator<1, T, REFERENCE, POINTER>
377 {
378  public:
379  enum { level = 0 };
380  typedef T value_type;
381  typedef REFERENCE reference;
382  typedef const value_type &const_reference;
383  typedef POINTER pointer;
384  typedef const value_type *const_pointer;
385  typedef typename MultiArrayShape<1>::type multi_difference_type;
387  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
388  typedef std::random_access_iterator_tag iterator_category;
389 
390  protected:
391  pointer m_ptr;
392 
393  public:
394  MultiIterator ()
395  : m_ptr (0)
396  {}
397 
398  MultiIterator (pointer ptr,
399  const difference_type *,
400  const difference_type *)
401  : m_ptr (ptr)
402  {}
403 
404  void operator++ ()
405  {
406  ++m_ptr;
407  }
408 
409  void operator-- ()
410  {
411  --m_ptr;
412  }
413 
415  {
416  MultiIterator ret = *this;
417  ++(*this);
418  return ret;
419  }
420 
422  {
423  MultiIterator ret = *this;
424  --(*this);
425  return ret;
426  }
427 
429  {
430  m_ptr += n;
431  return *this;
432  }
433 
435  {
436  m_ptr += d[level];
437  return *this;
438  }
439 
441  {
442  m_ptr -= n;
443  return *this;
444  }
445 
447  {
448  m_ptr -= d[level];
449  return *this;
450  }
451 
453  {
454  MultiIterator ret = *this;
455  ret += n;
456  return ret;
457  }
458 
460  {
461  MultiIterator ret = *this;
462  ret += d;
463  return ret;
464  }
465 
466  difference_type operator- (MultiIterator const & d) const
467  {
468  return (m_ptr - d.m_ptr);
469  }
470 
472  {
473  MultiIterator ret = *this;
474  ret -= n;
475  return ret;
476  }
477 
479  {
480  MultiIterator ret = *this;
481  ret -= d;
482  return ret;
483  }
484 
486  {
487  return m_ptr [n];
488  }
489 
491  {
492  return m_ptr [d[level]];
493  }
494 
495  reference operator* () const
496  {
497  return *m_ptr;
498  }
499 
500  pointer get () const
501  {
502  return m_ptr;
503  }
504 
505  pointer operator->() const
506  {
507  return &(operator*());
508  }
509 
510  bool operator!= (const MultiIterator &rhs) const
511  {
512  return m_ptr != rhs.m_ptr;
513  }
514 
515  bool operator== (const MultiIterator &rhs) const
516  {
517  return m_ptr == rhs.m_ptr;
518  }
519 
520  bool operator< (const MultiIterator &rhs) const
521  {
522  return m_ptr < rhs.m_ptr;
523  }
524 
525  bool operator<= (const MultiIterator &rhs) const
526  {
527  return m_ptr <= rhs.m_ptr;
528  }
529 
530  bool operator> (const MultiIterator &rhs) const
531  {
532  return m_ptr > rhs.m_ptr;
533  }
534 
535  bool operator>= (const MultiIterator &rhs) const
536  {
537  return m_ptr >= rhs.m_ptr;
538  }
539 
540  iterator iteratorForDimension(unsigned int d) const
541  {
542  vigra_precondition(d == 0,
543  "MultiIterator<1>::iteratorForDimension(d): d == 0 required");
544  const difference_type stride = 1;
545  return iterator(m_ptr, &stride, 0);
546  }
547 
548  template <unsigned int K>
549  MultiIterator<K+1, T, REFERENCE, POINTER> &
550  dim()
551  {
552  return *this;
553  }
554 
555  MultiIterator<1, T, REFERENCE, POINTER> &
556  dim0() { return *this; }
557 
558  protected:
559 
561  total_stride(typename multi_difference_type::const_iterator d) const
562  {
563  return d[level];
564  }
565 };
566 
567 /********************************************************/
568 /* */
569 /* MultiIterator<2> */
570 /* */
571 /********************************************************/
572 
573 //
574 template <class T, class REFERENCE, class POINTER>
575 class MultiIterator<2, T, REFERENCE, POINTER>
576 : public MultiIterator<1, T, REFERENCE, POINTER>
577 {
578  public:
579 
580  typedef MultiIterator<1, T, REFERENCE, POINTER> base_type;
581  enum { level = 1 };
582  typedef T value_type;
583  typedef REFERENCE reference;
584  typedef const value_type &const_reference;
585  typedef POINTER pointer;
586  typedef const value_type *const_pointer;
587  typedef typename MultiArrayShape<2>::type multi_difference_type;
589  typedef base_type next_type;
590  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
591  typedef multi_dimensional_traverser_tag iterator_category;
592 
593  protected:
594  const difference_type *m_stride;
595  const difference_type *m_shape;
596 
597  public:
598  /* use default copy constructor and assignment operator */
599 
600  MultiIterator ()
601  : base_type (),
602  m_stride (0), m_shape (0)
603  {}
604 
605  MultiIterator (pointer ptr,
606  const difference_type *stride,
607  const difference_type *shape)
608  : base_type (ptr, stride, shape),
609  m_stride (stride), m_shape (shape)
610  {}
611 
612  void operator++ ()
613  {
614  this->m_ptr += m_stride [level];
615  }
616 
617  void operator-- ()
618  {
619  this->m_ptr -= m_stride [level];
620  }
621 
623  {
624  MultiIterator ret = *this;
625  ++(*this);
626  return ret;
627  }
628 
630  {
631  MultiIterator ret = *this;
632  --(*this);
633  return ret;
634  }
635 
637  {
638  this->m_ptr += n * m_stride [level];
639  return *this;
640  }
641 
643  {
644  this->m_ptr += total_stride(d.begin());
645  return *this;
646  }
647 
649  {
650  this->m_ptr -= n * m_stride [level];
651  return *this;
652  }
653 
655  {
656  this->m_ptr -= total_stride(d.begin());
657  return *this;
658  }
659 
661  {
662  MultiIterator ret = *this;
663  ret += n;
664  return ret;
665  }
666 
668  {
669  MultiIterator ret = *this;
670  ret += d;
671  return ret;
672  }
673 
674  difference_type operator- (MultiIterator const & d) const
675  {
676  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
677  }
678 
680  {
681  MultiIterator ret = *this;
682  ret -= n;
683  return ret;
684  }
685 
687  {
688  MultiIterator ret = *this;
689  ret -= d;
690  return ret;
691  }
692 
694  {
695  return this->m_ptr [n*m_stride [level]];
696  }
697 
699  {
700  return this->m_ptr [total_stride(d.begin())];
701  }
702 
703  next_type begin () const
704  {
705  return *this;
706  }
707 
708  next_type end () const
709  {
710  next_type ret = *this;
711  ret += m_shape [level-1];
712  return ret;
713  }
714 
715  iterator iteratorForDimension(unsigned int d) const
716  {
717  vigra_precondition(d <= level,
718  "MultiIterator<N>::iteratorForDimension(d): d < N required");
719  return iterator(this->m_ptr, &m_stride [d], 0);
720  }
721 
722  template <unsigned int K>
723  MultiIterator<K+1, T, REFERENCE, POINTER> &
724  dim()
725  {
726  return *this;
727  }
728 
729  MultiIterator<1, T, REFERENCE, POINTER> &
730  dim0() { return *this; }
731  MultiIterator<2, T, REFERENCE, POINTER> &
732  dim1() { return *this; }
733 
734  protected:
735 
737  total_stride(typename multi_difference_type::const_iterator d) const
738  {
739  return d[level]*m_stride[level] + base_type::total_stride(d);
740  }
741 };
742 
743 /********************************************************/
744 /* */
745 /* MultiIterator<N> */
746 /* */
747 /********************************************************/
748 
749 /** \brief A multi-dimensional hierarchical iterator to be used with
750  \ref vigra::MultiArrayView if it is not strided.
751 
752  See \ref MultiIteratorPage for further documentation.
753 
754 <b>\#include</b> <<a href="multi__iterator_8hxx-source.html">vigra/multi_iterator.hxx</a>>
755 
756 Namespace: vigra
757 */
758 template <unsigned int N, class T, class REFERENCE, class POINTER>
760 : public MultiIterator<N-1, T, REFERENCE, POINTER>
761 {
762 public:
763 
764  /** the type of the parent in the inheritance hierarchy.
765  */
766  typedef MultiIterator<N-1, T, REFERENCE, POINTER> base_type;
767 
768  /** the iterator's level in the dimension hierarchy
769  */
770  enum { level = N-1 };
771 
772  /** the iterator's value type
773  */
774  typedef T value_type;
775 
776  /** reference type (result of operator[])
777  */
778  typedef REFERENCE reference;
779 
780  /** const reference type (result of operator[] const)
781  */
782  typedef const value_type &const_reference;
783 
784  /** pointer type
785  */
786  typedef POINTER pointer;
787 
788  /** const pointer type
789  */
790  typedef const value_type *const_pointer;
791 
792  /** multi difference type
793  (used for offsetting along all axes simultaneously)
794  */
796 
797  /** difference type (used for offsetting)
798  */
800 
801  /** the MultiIterator for the next lower dimension.
802  */
804 
805  /** the 1-dimensional iterator for this iterator hierarchy
806  (result of iteratorForDimension()).
807  */
809 
810  /** the iterator tag (image traverser)
811  */
812  typedef multi_dimensional_traverser_tag iterator_category;
813 
814  /* use default copy constructor and assignment operator */
815 
816  /** default constructor.
817  */
819  {}
820 
821  /** construct from pointer, strides (offset of a sample to the
822  next) for every dimension, and the shape.
823  */
825  const difference_type *stride,
826  const difference_type *shape)
827  : base_type (ptr, stride, shape)
828  {}
829 
830 
831  /** prefix-increment the iterator in it's current dimension
832  */
833  void operator++ ()
834  {
835  this->m_ptr += this->m_stride [level];
836  }
837 
838  /** prefix-decrement the iterator in it's current dimension
839  */
840  void operator-- ()
841  {
842  this->m_ptr -= this->m_stride [level];
843  }
844 
845  /** postfix-increment the iterator in it's current dimension
846  */
848  {
849  MultiIterator ret = *this;
850  ++(*this);
851  return ret;
852  }
853 
854  /** postfix-decrement the iterator in it's current dimension
855  */
857  {
858  MultiIterator ret = *this;
859  --(*this);
860  return ret;
861  }
862 
863  /** increment the iterator in it's current dimension
864  by the given value.
865  */
867  {
868  this->m_ptr += n * this->m_stride [level];
869  return *this;
870  }
871 
872  /** increment the iterator in all dimensions
873  by the given offset.
874  */
876  {
877  this->m_ptr += total_stride(d.begin());
878  return *this;
879  }
880 
881  /** decrement the iterator in it's current dimension
882  by the given value.
883  */
885  {
886  this->m_ptr -= n * this->m_stride [level];
887  return *this;
888  }
889 
890  /** decrement the iterator in all dimensions
891  by the given offset.
892  */
894  {
895  this->m_ptr -= total_stride(d.begin());
896  return *this;
897  }
898 
899  /** addition within current dimension
900  */
902  {
903  MultiIterator ret = *this;
904  ret += n;
905  return ret;
906  }
907 
908  /** addition along all dimensions
909  */
911  {
912  MultiIterator ret = *this;
913  ret += d;
914  return ret;
915  }
916 
917  /** difference of two iterators in the current dimension.
918  The result of this operation is undefined if the iterator
919  doesn't point to element 0 in all dimensions below its current dimension.
920  */
922  {
923  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
924  }
925 
926  /** subtraction within current dimension
927  */
929  {
930  MultiIterator ret = *this;
931  ret -= n;
932  return ret;
933  }
934 
935  /** subtraction along all dimensions
936  */
938  {
939  MultiIterator ret = *this;
940  ret -= d;
941  return ret;
942  }
943 
944 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
945  /** derefenrence item
946  */
947  reference operator* () const;
948 
949  /** get address of current item
950  */
951  pointer get () const;
952 
953  /** call method of current item
954  */
955  pointer operator->() const;
956 
957  /** inequality. True if iterators reference different items.
958  */
959  bool operator!= (const MultiIterator &rhs) const;
960 
961  /** equality. True if iterators reference the same items.
962  */
963  bool operator== (const MultiIterator &rhs) const;
964 
965  /** less than.
966  */
967  bool operator< (const MultiIterator &rhs) const;
968 
969  /** less or equal.
970  */
971  bool operator<= (const MultiIterator &rhs) const;
972 
973  /** greater than.
974  */
975  bool operator> (const MultiIterator &rhs) const;
976 
977  /** greater or equal.
978  */
979  bool operator>= (const MultiIterator &rhs) const;
980 #endif
981 
982  /** access the array element at the given offset in
983  the current dimension.
984  */
986  {
987  return this->m_ptr [n* this->m_stride [level]];
988  }
989 
990  /** access the array element at the given offset.
991  */
993  {
994  return this->m_ptr [total_stride(d.begin())];
995  }
996 
997  /** Return the (N-1)-dimensional multi-iterator that points to
998  the first (N-1)-dimensional subarray of the
999  N-dimensional array this iterator is referring to.
1000  The result is only valid if this iterator refers to location
1001  0 in <em>all</em> dimensions below its current dimension N,
1002  otherwise it is undefined. Usage:
1003 
1004  \code
1005 
1006  MultiIterator<2, int> outer = ...; // this iterator
1007 
1008  MultiIterator<2, int>::next_type inner = outer.begin();
1009  for(; inner != outer.end(); ++inner)
1010  {
1011  // manipulate current 1D subimage
1012  }
1013  \endcode
1014  */
1015  next_type begin () const
1016  {
1017  return *this;
1018  }
1019 
1020  /** Return the (N-1)-dimensional multi-iterator that points beyond
1021  the last (N-1)-dimensional subarray of the
1022  N-dimensional array this iterator is referring to.
1023  The result is only valid if this iterator refers to location
1024  0 in <em>all</em> dimensions below its current dimension N,
1025  otherwise it is undefined.
1026  */
1027  next_type end () const
1028  {
1029  next_type ret = *this;
1030  ret += this->m_shape [level-1];
1031  return ret;
1032  }
1033 
1034  /** Get a 1-dimensional, STL-compatible iterator for the
1035  given dimension, pointing to the current element of <TT>this</TT>.
1036  Usage:
1037 
1038  \code
1039 
1040  MultiIterator<3, int> outer = ...; // this iterator
1041 
1042  MultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
1043  MultiIterator<3, int>::iterator end = i + height;
1044  for(; i != end; ++i)
1045  {
1046  // go down the current column starting at the location of 'outer'
1047  }
1048  \endcode
1049  */
1050  iterator iteratorForDimension(unsigned int d) const
1051  {
1052  vigra_precondition(d <= level,
1053  "MultiIterator<N>::iteratorForDimension(d): d < N required");
1054  return iterator(this->m_ptr, &this->m_stride [d], 0);
1055  }
1056  /** Return the multi-iterator that operates on dimension K in order
1057  to manipulate this dimension directly. Usage:
1058 
1059  \code
1060 
1061  MultiIterator<3, int> i3 = ...;
1062 
1063  i3.template dim<2>()++; // increment outer dimension
1064  i3.template dim<0>()++; // increment inner dimension
1065  \endcode
1066 
1067  For convenience, the same functionality is also available
1068  as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
1069 
1070  \code
1071 
1072  MultiIterator<3, int> i3 = ...;
1073 
1074  i3.dim2()++; // increment outer dimension
1075  i3.dim0()++; // increment inner dimension
1076  \endcode
1077  */
1078  template <unsigned int K>
1081  {
1082  return *this;
1083  }
1084 
1086  dim0() { return *this; }
1087  MultiIterator<2, T, REFERENCE, POINTER> &
1088  dim1() { return *this; }
1089  MultiIterator<3, T, REFERENCE, POINTER> &
1090  dim2() { return *this; }
1091  MultiIterator<4, T, REFERENCE, POINTER> &
1092  dim3() { return *this; }
1093  MultiIterator<5, T, REFERENCE, POINTER> &
1094  dim4() { return *this; }
1095 
1096  protected:
1097 
1099  total_stride(typename multi_difference_type::const_iterator d) const
1100  {
1101  return d[level]*this->m_stride[level] + base_type::total_stride(d);
1102  }
1103 
1104 };
1105 
1106 /********************************************************/
1107 /* */
1108 /* StridedMultiIterator */
1109 /* */
1110 /********************************************************/
1111 
1112 template <unsigned int N, class T, class REFERENCE, class POINTER>
1113 class StridedMultiIterator;
1114 
1115 /********************************************************/
1116 /* */
1117 /* StridedMultiIterator<1> */
1118 /* */
1119 /********************************************************/
1120 
1121 //
1122 template <class T, class REFERENCE, class POINTER>
1123 class StridedMultiIterator<1, T, REFERENCE, POINTER>
1124 {
1125  public:
1126  enum { level = 0 };
1127  typedef T value_type;
1128  typedef REFERENCE reference;
1129  typedef const value_type &const_reference;
1130  typedef POINTER pointer;
1131  typedef const value_type *const_pointer;
1132  typedef typename MultiArrayShape<1>::type multi_difference_type;
1134  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1135  typedef std::random_access_iterator_tag iterator_category;
1136 
1137  protected:
1138  pointer m_ptr;
1139  difference_type m_stride;
1140 
1141  /* use default copy constructor and assignment operator */
1142 
1143  public:
1145  : m_ptr (0), m_stride (0)
1146  {}
1147 
1149  const difference_type *stride,
1150  const difference_type *)
1151  : m_ptr (ptr), m_stride (stride [level])
1152  {}
1153 
1154  void operator++ ()
1155  {
1156  m_ptr += m_stride;
1157  }
1158 
1159  void operator-- ()
1160  {
1161  m_ptr -= m_stride;
1162  }
1163 
1165  {
1166  StridedMultiIterator ret = *this;
1167  ++(*this);
1168  return ret;
1169  }
1170 
1172  {
1173  StridedMultiIterator ret = *this;
1174  --(*this);
1175  return ret;
1176  }
1177 
1179  {
1180  m_ptr += n * m_stride;
1181  return *this;
1182  }
1183 
1185  {
1186  m_ptr += d[level] * m_stride;
1187  return *this;
1188  }
1189 
1191  {
1192  m_ptr -= n * m_stride;
1193  return *this;
1194  }
1195 
1197  {
1198  m_ptr -= d[level] * m_stride;
1199  return *this;
1200  }
1201 
1203  {
1204  StridedMultiIterator ret = *this;
1205  ret += n;
1206  return ret;
1207  }
1208 
1210  {
1211  StridedMultiIterator ret = *this;
1212  ret += d;
1213  return ret;
1214  }
1215 
1217  {
1218  return (m_ptr - d.m_ptr) / m_stride;
1219  }
1220 
1222  {
1223  StridedMultiIterator ret = *this;
1224  ret -= n;
1225  return ret;
1226  }
1227 
1229  {
1230  StridedMultiIterator ret = *this;
1231  ret -= d;
1232  return ret;
1233  }
1234 
1236  {
1237  return m_ptr [n*m_stride];
1238  }
1239 
1241  {
1242  return m_ptr [d[level]*m_stride];
1243  }
1244 
1245  reference operator* () const
1246  {
1247  return *m_ptr;
1248  }
1249 
1250  pointer get () const
1251  {
1252  return m_ptr;
1253  }
1254 
1255  pointer operator->() const
1256  {
1257  return &(operator*());
1258  }
1259 
1260  bool operator!= (const StridedMultiIterator &rhs) const
1261  {
1262  return m_ptr != rhs.m_ptr;
1263  }
1264 
1265  bool operator== (const StridedMultiIterator &rhs) const
1266  {
1267  return m_ptr == rhs.m_ptr;
1268  }
1269 
1270  bool operator< (const StridedMultiIterator &rhs) const
1271  {
1272  return m_ptr < rhs.m_ptr;
1273  }
1274 
1275  bool operator<= (const StridedMultiIterator &rhs) const
1276  {
1277  return m_ptr <= rhs.m_ptr;
1278  }
1279 
1280  bool operator> (const StridedMultiIterator &rhs) const
1281  {
1282  return m_ptr > rhs.m_ptr;
1283  }
1284 
1285  bool operator>= (const StridedMultiIterator &rhs) const
1286  {
1287  return m_ptr >= rhs.m_ptr;
1288  }
1289 
1290  iterator iteratorForDimension(unsigned int d) const
1291  {
1292  vigra_precondition(d == 0,
1293  "StridedMultiIterator<1>::iteratorForDimension(d): d == 0 required");
1294  const difference_type stride = 1;
1295  return iterator(m_ptr, &stride, 0);
1296  }
1297 
1298  template <unsigned int K>
1299  StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1300  dim()
1301  {
1302  return *this;
1303  }
1304 
1305  StridedMultiIterator<1, T, REFERENCE, POINTER> &
1306  dim0() { return *this; }
1307 
1308  protected:
1309 
1311  total_stride(typename multi_difference_type::const_iterator d) const
1312  {
1313  return d[level] * m_stride;
1314  }
1315 };
1316 
1317 /********************************************************/
1318 /* */
1319 /* StridedMultiIterator<2> */
1320 /* */
1321 /********************************************************/
1322 
1323 //
1324 template <class T, class REFERENCE, class POINTER>
1325 class StridedMultiIterator<2, T, REFERENCE, POINTER>
1326 : public StridedMultiIterator<1, T, REFERENCE, POINTER>
1327 {
1328  public:
1329 
1330  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
1331  enum { level = 1 };
1332  typedef T value_type;
1333  typedef REFERENCE reference;
1334  typedef const value_type &const_reference;
1335  typedef POINTER pointer;
1336  typedef const value_type *const_pointer;
1337  typedef typename MultiArrayShape<2>::type multi_difference_type;
1339  typedef base_type next_type;
1340  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1341  typedef multi_dimensional_traverser_tag iterator_category;
1342 
1343  protected:
1344  const difference_type *m_stride;
1345  const difference_type *m_shape;
1346 
1347  public:
1348  /* use default copy constructor and assignment operator */
1349 
1351  : base_type (),
1352  m_stride (0), m_shape (0)
1353  {}
1354 
1356  const difference_type *stride,
1357  const difference_type *shape)
1358  : base_type (ptr, stride, shape),
1359  m_stride (stride), m_shape (shape)
1360  {}
1361 
1362  void operator++ ()
1363  {
1364  this->m_ptr += m_stride [level];
1365  }
1366 
1367  void operator-- ()
1368  {
1369  this->m_ptr -= m_stride [level];
1370  }
1371 
1373  {
1374  StridedMultiIterator ret = *this;
1375  ++(*this);
1376  return ret;
1377  }
1378 
1380  {
1381  StridedMultiIterator ret = *this;
1382  --(*this);
1383  return ret;
1384  }
1385 
1387  {
1388  this->m_ptr += n * m_stride [level];
1389  return *this;
1390  }
1391 
1393  {
1394  this->m_ptr += total_stride(d.begin());
1395  return *this;
1396  }
1397 
1399  {
1400  this->m_ptr -= n * m_stride [level];
1401  return *this;
1402  }
1403 
1405  {
1406  this->m_ptr -= total_stride(d.begin());
1407  return *this;
1408  }
1409 
1411  {
1412  StridedMultiIterator ret = *this;
1413  ret += n;
1414  return ret;
1415  }
1416 
1418  {
1419  StridedMultiIterator ret = *this;
1420  ret += d;
1421  return ret;
1422  }
1423 
1425  {
1426  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1427  }
1428 
1430  {
1431  StridedMultiIterator ret = *this;
1432  ret -= n;
1433  return ret;
1434  }
1435 
1437  {
1438  StridedMultiIterator ret = *this;
1439  ret -= d;
1440  return ret;
1441  }
1442 
1444  {
1445  return this->m_ptr [n*m_stride [level]];
1446  }
1447 
1449  {
1450  return this->m_ptr [total_stride(d.begin())];
1451  }
1452 
1453  next_type begin () const
1454  {
1455  return *this;
1456  }
1457 
1458  next_type end () const
1459  {
1460  next_type ret = *this;
1461  ret += m_shape [level-1];
1462  return ret;
1463  }
1464 
1465  iterator iteratorForDimension(unsigned int d) const
1466  {
1467  vigra_precondition(d <= level,
1468  "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
1469  return iterator(this->m_ptr, &m_stride [d], 0);
1470  }
1471 
1472  template <unsigned int K>
1473  StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1474  dim()
1475  {
1476  return *this;
1477  }
1478 
1479  StridedMultiIterator<1, T, REFERENCE, POINTER> &
1480  dim0() { return *this; }
1481  StridedMultiIterator<2, T, REFERENCE, POINTER> &
1482  dim1() { return *this; }
1483 
1484  protected:
1485 
1487  total_stride(typename multi_difference_type::const_iterator d) const
1488  {
1489  return d[level]*m_stride[level] + base_type::total_stride(d);
1490  }
1491 };
1492 
1493 /********************************************************/
1494 /* */
1495 /* StridedMultiIterator<N> */
1496 /* */
1497 /********************************************************/
1498 
1499 /** \brief A multi-dimensional hierarchical iterator to be used with
1500  \ref vigra::MultiArrayView if it is not strided.
1501 
1502  See \ref MultiIteratorPage for further documentation.
1503 
1504 <b>\#include</b> <<a href="multi__iterator_8hxx-source.html">vigra/multi_iterator.hxx</a>>
1505 
1506 Namespace: vigra
1507 */
1508 template <unsigned int N, class T, class REFERENCE, class POINTER>
1510 : public StridedMultiIterator<N-1, T, REFERENCE, POINTER>
1511 {
1512 public:
1513 
1514  /** the type of the parent in the inheritance hierarchy.
1515  */
1516  typedef StridedMultiIterator<N-1, T, REFERENCE, POINTER> base_type;
1517 
1518  /** the iterator's level in the dimension hierarchy
1519  */
1520  enum { level = N-1 };
1521 
1522  /** the iterator's value type
1523  */
1524  typedef T value_type;
1525 
1526  /** reference type (result of operator[])
1527  */
1528  typedef REFERENCE reference;
1529 
1530  /** const reference type (result of operator[] const)
1531  */
1532  typedef const value_type &const_reference;
1533 
1534  /** pointer type
1535  */
1536  typedef POINTER pointer;
1537 
1538  /** const pointer type
1539  */
1540  typedef const value_type *const_pointer;
1541 
1542  /** multi difference type
1543  (used for offsetting along all axes simultaneously)
1544  */
1546 
1547  /** difference type (used for offsetting)
1548  */
1550 
1551  /** the StridedMultiIterator for the next lower dimension.
1552  */
1554 
1555  /** the 1-dimensional iterator for this iterator hierarchy
1556  (result of iteratorForDimension()).
1557  */
1559 
1560  /** the iterator tag (image traverser)
1561  */
1562  typedef multi_dimensional_traverser_tag iterator_category;
1563 
1564  /* use default copy constructor and assignment operator */
1565 
1566  /** default constructor.
1567  */
1569  {}
1570 
1571  /** construct from pointer, strides (offset of a sample to the
1572  next) for every dimension, and the shape.
1573  */
1575  const difference_type *stride,
1576  const difference_type *shape)
1577  : base_type (ptr, stride, shape)
1578  {}
1579 
1580 
1581  /** prefix-increment the iterator in it's current dimension
1582  */
1584  {
1585  this->m_ptr += this->m_stride [level];
1586  }
1587 
1588  /** prefix-decrement the iterator in it's current dimension
1589  */
1591  {
1592  this->m_ptr -= this->m_stride [level];
1593  }
1594 
1595  /** postfix-increment the iterator in it's current dimension
1596  */
1598  {
1599  StridedMultiIterator ret = *this;
1600  ++(*this);
1601  return ret;
1602  }
1603 
1604  /** postfix-decrement the iterator in it's current dimension
1605  */
1607  {
1608  StridedMultiIterator ret = *this;
1609  --(*this);
1610  return ret;
1611  }
1612 
1613  /** increment the iterator in it's current dimension
1614  by the given value.
1615  */
1617  {
1618  this->m_ptr += n * this->m_stride [level];
1619  return *this;
1620  }
1621 
1622  /** increment the iterator in all dimensions
1623  by the given offset.
1624  */
1626  {
1627  this->m_ptr += total_stride(d.begin());
1628  return *this;
1629  }
1630 
1631  /** decrement the iterator in it's current dimension
1632  by the given value.
1633  */
1635  {
1636  this->m_ptr -= n * this->m_stride [level];
1637  return *this;
1638  }
1639 
1640  /** decrement the iterator in all dimensions
1641  by the given offset.
1642  */
1644  {
1645  this->m_ptr -= total_stride(d.begin());
1646  return *this;
1647  }
1648 
1649  /** addition within current dimension
1650  */
1652  {
1653  StridedMultiIterator ret = *this;
1654  ret += n;
1655  return ret;
1656  }
1657 
1658  /** addition along all dimensions
1659  */
1661  {
1662  StridedMultiIterator ret = *this;
1663  ret += d;
1664  return ret;
1665  }
1666 
1667  /** difference of two iterators in the current dimension.
1668  The result of this operation is undefined if the iterator
1669  doesn't point to element 0 in all dimensions below its current dimension.
1670  */
1672  {
1673  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1674  }
1675 
1676  /** subtraction within current dimension
1677  */
1679  {
1680  StridedMultiIterator ret = *this;
1681  ret -= n;
1682  return ret;
1683  }
1684 
1685  /** subtraction along all dimensions
1686  */
1688  {
1689  StridedMultiIterator ret = *this;
1690  ret -= d;
1691  return ret;
1692  }
1693 
1694 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
1695  /** derefenrence item
1696  */
1697  reference operator* () const;
1698 
1699  /** get address of current item
1700  */
1701  pointer get () const;
1702 
1703  /** call method of current item
1704  */
1705  pointer operator->() const;
1706 
1707  /** inequality. True if iterators reference different items.
1708  */
1709  bool operator!= (const StridedMultiIterator &rhs) const;
1710 
1711  /** equality. True if iterators reference the same items.
1712  */
1713  bool operator== (const StridedMultiIterator &rhs) const;
1714 
1715  /** less than.
1716  */
1717  bool operator< (const StridedMultiIterator &rhs) const;
1718 
1719  /** less or equal.
1720  */
1721  bool operator<= (const StridedMultiIterator &rhs) const;
1722 
1723  /** greater than.
1724  */
1725  bool operator> (const StridedMultiIterator &rhs) const;
1726 
1727  /** greater or equal.
1728  */
1729  bool operator>= (const StridedMultiIterator &rhs) const;
1730 #endif
1731 
1732  /** access the array element at the given offset in
1733  the current dimension.
1734  */
1736  {
1737  return this->m_ptr [n* this->m_stride [level]];
1738  }
1739 
1740  /** access the array element at the given offset.
1741  */
1743  {
1744  return this->m_ptr [total_stride(d.begin())];
1745  }
1746 
1747  /** Return the (N-1)-dimensional multi-iterator that points to
1748  the first (N-1)-dimensional subarray of the
1749  N-dimensional array this iterator is referring to.
1750  The result is only valid if this iterator refers to location
1751  0 in <em>all</em> dimensions below its current dimension N,
1752  otherwise it is undefined. Usage:
1753 
1754  \code
1755 
1756  StridedMultiIterator<2, int> outer = ...; // this iterator
1757 
1758  StridedMultiIterator<2, int>::next_type inner = outer.begin();
1759  for(; inner != outer.end(); ++inner)
1760  {
1761  // manipulate current 1D subimage
1762  }
1763  \endcode
1764  */
1765  next_type begin () const
1766  {
1767  return *this;
1768  }
1769 
1770  /** Return the (N-1)-dimensional multi-iterator that points beyond
1771  the last (N-1)-dimensional subarray of the
1772  N-dimensional array this iterator is referring to.
1773  The result is only valid if this iterator refers to location
1774  0 in <em>all</em> dimensions below its current dimension N,
1775  otherwise it is undefined.
1776  */
1777  next_type end () const
1778  {
1779  next_type ret = *this;
1780  ret += this->m_shape [level-1];
1781  return ret;
1782  }
1783 
1784  /** Get a 1-dimensional, STL-compatible iterator for the
1785  given dimension, pointing to the current element of <TT>this</TT>.
1786  Usage:
1787 
1788  \code
1789 
1790  StridedMultiIterator<3, int> outer = ...; // this iterator
1791 
1792  StridedMultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
1793  StridedMultiIterator<3, int>::iterator end = i + height;
1794  for(; i != end; ++i)
1795  {
1796  // go down the current column starting at the location of 'outer'
1797  }
1798  \endcode
1799  */
1800  iterator iteratorForDimension(unsigned int d) const
1801  {
1802  vigra_precondition(d <= level,
1803  "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
1804  return iterator(this->m_ptr, &this->m_stride [d], 0);
1805  }
1806  /** Return the multi-iterator that operates on dimension K in order
1807  to manipulate this dimension directly. Usage:
1808 
1809  \code
1810 
1811  StridedMultiIterator<3, int> i3 = ...;
1812 
1813  i3.template dim<2>()++; // increment outer dimension
1814  i3.template dim<0>()++; // increment inner dimension
1815  \endcode
1816 
1817  For convenience, the same functionality is also available
1818  as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
1819 
1820  \code
1821 
1822  StridedMultiIterator<3, int> i3 = ...;
1823 
1824  i3.dim2()++; // increment outer dimension
1825  i3.dim0()++; // increment inner dimension
1826  \endcode
1827  */
1828  template <unsigned int K>
1831  {
1832  return *this;
1833  }
1834 
1836  dim0() { return *this; }
1837  StridedMultiIterator<2, T, REFERENCE, POINTER> &
1838  dim1() { return *this; }
1839  StridedMultiIterator<3, T, REFERENCE, POINTER> &
1840  dim2() { return *this; }
1841  StridedMultiIterator<4, T, REFERENCE, POINTER> &
1842  dim3() { return *this; }
1843  StridedMultiIterator<5, T, REFERENCE, POINTER> &
1844  dim4() { return *this; }
1845 
1846  protected:
1847 
1849  total_stride(typename multi_difference_type::const_iterator d) const
1850  {
1851  return d[level]*this->m_stride[level] + base_type::total_stride(d);
1852  }
1853 
1854 };
1855 
1856 //@}
1857 
1858 } // namespace vigra
1859 
1860 #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.7.1 (Tue Jul 10 2012)