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

multi_iterator.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2003-2012 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 #ifndef VIGRA_MULTI_ITERATOR_HXX
38 #define VIGRA_MULTI_ITERATOR_HXX
39 
40 #include <sys/types.h>
41 #include "iteratortags.hxx"
42 #include "multi_iterator_coupled.hxx"
43 
44 namespace vigra {
45 
46 template<unsigned int N, class DirectedTag>
47 class GridGraph;
48 
49 /** \addtogroup MultiIteratorGroup
50 */
51 //@{
52 
53  /** \brief Iterate over a virtual array where each element contains its coordinate.
54 
55  MultiCoordinateIterator behaves like a read-only random access iterator.
56  It moves accross the given region of interest in scan-order (with the first
57  index changing most rapidly), and dereferencing the iterator returns the
58  coordinate (i.e. multi-dimensional index) of the current array element.
59  The functionality is thus similar to a meshgrid in Matlab or numpy.
60 
61  Internally, it is just a wrapper of a \ref CoupledScanOrderIterator that
62  has been created without any array and whose reference type is not a
63  \ref CoupledHandle, but the coordinate itself.
64 
65  The iterator supports all functions listed in the STL documentation for
66  <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
67 
68  <b>Usage:</b>
69 
70  <b>\#include</b> <vigra/multi_iterator.hxx><br/>
71  Namespace: vigra
72 
73  \code
74  MultiCoordinateIterator<3> i(Shape3(3,2,1)), end = i.getEndIterator();
75 
76  for(; i != end; ++i)
77  std::cout << *i << "\n";
78 
79  // Output:
80  // (0, 0, 0)
81  // (1, 0, 0)
82  // (2, 0, 0)
83  // (0, 1, 0)
84  // (1, 1, 0)
85  // (2, 1, 0)
86  \endcode
87  */
88 template<unsigned int N>
90  : public CoupledScanOrderIterator<N>
91 {
92  public:
94 
95  typedef typename base_type::shape_type shape_type;
96  typedef typename base_type::difference_type difference_type;
98  typedef std::random_access_iterator_tag iterator_category;
99 
100  typedef typename base_type::value_type handle_type;
101  typedef typename handle_type::value_type value_type;
102  typedef typename handle_type::reference reference;
103  typedef typename handle_type::const_reference const_reference;
104  typedef typename handle_type::pointer pointer;
105  typedef typename handle_type::const_pointer const_pointer;
106 
108  : base_type(handle_type())
109  {}
110 
111  explicit MultiCoordinateIterator(shape_type const & shape)
112  : base_type(handle_type(shape))
113  {}
114 
115  explicit MultiCoordinateIterator(shape_type const & start, shape_type const & end)
116  : base_type(handle_type(end))
117  {
118  this->restrictToSubarray(start, end);
119  }
120 
121  template<class DirectedTag>
123  : base_type(handle_type(g.shape()))
124  {}
125 
126  // dereferencing the iterator yields the coordinate object
127  // (used as vertex_descriptor)
128  reference operator*()
129  {
130  return this->template get<0>();
131  }
132 
133  const_reference operator*() const
134  {
135  return this->template get<0>();
136  }
137 
138  operator value_type() const
139  {
140  return *(*this);
141  }
142 
143  pointer operator->()
144  {
145  return &this->template get<0>();
146  }
147 
148  const_pointer operator->() const
149  {
150  return &this->template get<0>();
151  }
152 
153  value_type operator[](MultiArrayIndex i) const
154  {
155  return *(MultiCoordinateIterator(*this) += i);
156  }
157 
158  MultiCoordinateIterator & operator++()
159  {
160  base_type::operator++();
161  return *this;
162  }
163 
164  MultiCoordinateIterator operator++(int)
165  {
166  MultiCoordinateIterator res(*this);
167  ++*this;
168  return res;
169  }
170 
172  {
173  base_type::operator+=(i);
174  return *this;
175  }
176 
177  MultiCoordinateIterator & operator+=(const shape_type &coordOffset)
178  {
179  base_type::operator+=(coordOffset);
180  return *this;
181  }
182 
183  MultiCoordinateIterator & operator--()
184  {
185  base_type::operator--();
186  return *this;
187  }
188 
189  MultiCoordinateIterator operator--(int)
190  {
191  MultiCoordinateIterator res(*this);
192  --*this;
193  return res;
194  }
195 
197  {
198  return operator+=(-i);
199  }
200 
201  MultiCoordinateIterator & operator-=(const shape_type &coordOffset)
202  {
203  return operator+=(-coordOffset);
204  }
205 
206  MultiCoordinateIterator getEndIterator() const
207  {
209  }
210 
211  MultiCoordinateIterator operator+(MultiArrayIndex d) const
212  {
213  return MultiCoordinateIterator(*this) += d;
214  }
215 
216  MultiCoordinateIterator operator-(MultiArrayIndex d) const
217  {
218  return MultiCoordinateIterator(*this) -= d;
219  }
220 
221  MultiCoordinateIterator operator+(const shape_type &coordOffset) const
222  {
223  return MultiCoordinateIterator(*this) += coordOffset;
224  }
225 
226  MultiCoordinateIterator operator-(const shape_type &coordOffset) const
227  {
228  return MultiCoordinateIterator(*this) -= coordOffset;
229  }
230 
231  MultiArrayIndex operator-(const MultiCoordinateIterator & other) const
232  {
233  return base_type::operator-(other);
234  }
235 
236  protected:
237  MultiCoordinateIterator(base_type const & base)
238  : base_type(base)
239  {}
240 };
241 
242  /** \brief Sequential iterator for MultiArrayView.
243 
244  This iterator provides STL-compatible random access iterator functionality for arbitrary
245  \ref MultiArrayView instances, regardless of their shapes and strides. The
246  class uses an implementation that minimizes speed penalties that could result from
247  non-trivial strides. The <i>scan-order</i> is defined such that dimensions are iterated
248  from front to back (first to last).
249 
250  You normally construct instances of this class by calling \ref MultiArrayView::begin()
251  and \ref MultiArrayView::end().
252 
253  The iterator supports all functions listed in the STL documentation for
254  <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterators</a>.
255 
256  <b>\#include</b> <vigra/multi_iterator.hxx><br/>
257  Namespace: vigra
258  */
259 template <unsigned int N, class T, class REFERENCE, class POINTER>
262 {
263  public:
265 
266  typedef typename base_type::shape_type shape_type;
267  typedef typename base_type::difference_type difference_type;
269  typedef std::random_access_iterator_tag iterator_category;
270 
271  typedef T value_type;
272  typedef REFERENCE reference;
273  typedef T const & const_reference;
274  typedef POINTER pointer;
275  typedef T const * const_pointer;
276 
278  : base_type()
279  {}
280 
281  template <class S>
282  explicit StridedScanOrderIterator(MultiArrayView<N, T, S> const & view)
283  : base_type(createCoupledIterator(view))
284  {}
285 
286  StridedScanOrderIterator(POINTER p, shape_type const & shape, shape_type const & strides)
287  : base_type(createCoupledIterator(MultiArrayView<N, T, StridedArrayTag>(shape, strides, const_cast<T *>(p))))
288  {}
289 
290  reference operator*()
291  {
292  return this->template get<1>();
293  }
294 
295  const_reference operator*() const
296  {
297  return this->template get<1>();
298  }
299 
300  pointer operator->()
301  {
302  return &this->template get<1>();
303  }
304 
305  const_pointer operator->() const
306  {
307  return &this->template get<1>();
308  }
309 
310  reference operator[](MultiArrayIndex i)
311  {
312  return *(StridedScanOrderIterator(*this) += i);
313  }
314 
315  const_reference operator[](MultiArrayIndex i) const
316  {
317  return *(StridedScanOrderIterator(*this) += i);
318  }
319 
320  StridedScanOrderIterator & operator++()
321  {
322  base_type::operator++();
323  return *this;
324  }
325 
326  StridedScanOrderIterator operator++(int)
327  {
328  StridedScanOrderIterator res(*this);
329  ++*this;
330  return res;
331  }
332 
334  {
336  return *this;
337  }
338 
339  StridedScanOrderIterator & operator+=(const shape_type &coordOffset)
340  {
341  base_type::operator+=(coordOffset);
342  return *this;
343  }
344 
345  StridedScanOrderIterator & operator--()
346  {
347  base_type::operator--();
348  return *this;
349  }
350 
351  StridedScanOrderIterator operator--(int)
352  {
353  StridedScanOrderIterator res(*this);
354  --*this;
355  return res;
356  }
357 
359  {
360  return operator+=(-i);
361  }
362 
363  StridedScanOrderIterator & operator-=(const shape_type &coordOffset)
364  {
365  return operator+=(-coordOffset);
366  }
367 
368  StridedScanOrderIterator getEndIterator() const
369  {
370  return StridedScanOrderIterator(base_type::getEndIterator());
371  }
372 
374  {
375  return StridedScanOrderIterator(*this) += d;
376  }
377 
379  {
380  return StridedScanOrderIterator(*this) -= d;
381  }
382 
384  {
385  return base_type::operator-(other);
386  }
387 
388  StridedScanOrderIterator operator+(const shape_type &coordOffset) const
389  {
390  return StridedScanOrderIterator(*this) += coordOffset;
391  }
392 
393  StridedScanOrderIterator operator-(const shape_type &coordOffset) const
394  {
395  return StridedScanOrderIterator(*this) -= coordOffset;
396  }
397 
398  MultiArrayIndex index() const
399  {
400  return this->scanOrderIndex();
401  }
402 
403  protected:
404  StridedScanOrderIterator(base_type const & base)
405  : base_type(base)
406  {}
407 };
408 
409 //@}
410 
411 /** \page MultiIteratorPage Multi-dimensional Array Iterators
412 
413 General iterators for arrays of arbitrary dimension.
414 
415 <p>
416 <UL style="list-style-image:url(documents/bullet.gif)">
417 <LI> \ref vigra::MultiArrayShape
418  <BR>&nbsp;&nbsp;&nbsp;<em>Difference type for \ref vigra::MultiArrayView or \ref vigra::MultiIterator</em>
419 <LI> \ref vigra::MultiIterator
420  <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for unstrided \ref vigra::MultiArrayView</em>
421 <LI> \ref vigra::StridedMultiIterator
422  <BR>&nbsp;&nbsp;&nbsp;<em>Iterator for strided \ref vigra::MultiArrayView</em>
423 <LI> \ref vigra::StridedScanOrderIterator
424  <BR>&nbsp;&nbsp;&nbsp;<em>STL-compatible random access iterator for \ref vigra::MultiArrayView</em>
425 <LI> \ref vigra::CoupledScanOrderIterator
426  <BR>&nbsp;&nbsp;&nbsp;<em>Iterate over multiple images simultaneously in scan order</em>
427 </UL>
428 </p>
429 
430 <p>
431  The Multidimensional Iterator concept allows navigation on arrays
432  of arbitrary dimension. It provides two modes of iteration:
433  <em>direct traversal</em>, and <em>hierarchical traversal</em>.
434  In general, hierarchical traversal will be faster, while only
435  direct traversal allows for true random access in all dimensions.
436  Via the <tt>dim<K>()</tt> function, operations applying to a particular
437  dimension can be used in the direct traversal mode. In contrast,
438  direct traversal functions should not be used in the hierarchical mode
439  because the hierarchical functions are only well-defined if the
440  iterator points to element 0 in all dimensions below its current dimension.
441  The current dimension of a <tt>MultiIterator<N, ...></tt> is <tt>N-1</tt>.
442 </p>
443 <h3>General Requirements for MultiIterator</h3>
444 <p>
445 <table border=2 cellspacing=0 cellpadding=2 width="100%">
446 <tr><th colspan=2>
447  Local Types
448  </th><th>
449  Meaning
450  </th>
451 </tr>
452 <tr><td colspan=2>
453  <tt>MultiIterator::value_type</tt></td><td>the underlying arrays's pixel type</td>
454 </tr>
455 <tr><td colspan=2>
456  <tt>MultiIterator::reference</tt></td>
457  <td>the iterator's reference type (return type of <TT>*iter</TT>). Will be
458  <tt>value_type &</tt> for a mutable iterator, and convertible to
459  <tt>value_type const &</tt> for a const iterator.</td>
460 </tr>
461 <tr><td colspan=2>
462  <tt>MultiIterator::pointer</tt></td>
463  <td>the iterator's pointer type (return type of <TT>iter.operator->()</TT>). Will be
464  <tt>value_type *</tt> for a mutable iterator, and convertible to
465  <tt>value_type const *</tt> for a const iterator.</td>
466 </tr>
467 <tr><td colspan=2>
468  <tt>MultiIterator::iterator_category</tt></td>
469  <td>the iterator tag (<tt>vigra::multi_dimensional_traverser_tag</tt>)</td>
470 </tr>
471 <tr><th>
472  Operation
473  </th><th>
474  Result
475  </th><th>
476  Semantics
477  </th>
478 </tr>
479 <tr><td colspan=2>
480  <tt>MultiIterator k;</tt></td><td>default constructor</td>
481 </tr>
482 <tr><td colspan=2>
483  <tt>MultiIterator k(i);</tt></td><td>copy constructor</td>
484 </tr>
485 <tr>
486  <td><tt>k = i</tt></td>
487  <td><tt>MultiIterator &</tt></td><td>assignment</td>
488 </tr>
489 <tr>
490  <td><tt>i == j</tt></td><td><tt>bool</tt></td>
491  <td>equality (iterators point to the same element)</td>
492 </tr>
493 <tr>
494  <td><tt>i != j</tt></td><td><tt>bool</tt></td>
495  <td>inequality (iterators don't point to the same element)</td>
496 </tr>
497 <tr>
498  <td><tt>*i</tt></td><td><tt>MultiIterator::reference</tt></td>
499  <td>access the current element</td>
500 </tr>
501 <tr>
502  <td><tt>i->member()</tt></td><td>depends on operation</td>
503  <td>call member function of underlying pixel type via <tt>operator-></tt> of iterator</td>
504 </tr>
505 </table>
506 </p>
507 <h3>Requirements for Direct Traversal</h3>
508 <p>
509 <table border=2 cellspacing=0 cellpadding=2 width="100%">
510 <tr><th colspan=2>
511  Local Types
512  </th><th>
513  Meaning
514  </th>
515 </tr>
516 <tr><td colspan=2>
517  <tt>MultiIterator::multi_difference_type</tt></td>
518  <td>the iterator's multi-dimensional difference type (<TT>TinyVector<MultiArrayIndex, N></TT>)</td>
519 </tr>
520 <tr><th>
521  Operation
522  </th><th>
523  Result
524  </th><th>
525  Semantics
526  </th>
527 </tr>
528 <tr>
529  <td><tt>i += diff</tt></td><td><tt>MultiIterator &</tt></td>
530  <td>add offset to current position</td>
531 </tr>
532 <tr>
533  <td><tt>i -= diff</tt></td><td><tt>MultiIterator &</tt></td>
534  <td>subtract offset from current position</td>
535 </tr>
536 <tr>
537  <td><tt>i + diff</tt></td><td><tt>MultiIterator</tt></td>
538  <td>create traverser by adding offset</td>
539 </tr>
540 <tr>
541  <td><tt>i - diff</tt></td><td><tt>MultiIterator</tt></td>
542  <td>create traverser by subtracting offset</td>
543 </tr>
544 <tr>
545  <td><tt>i[diff]</tt></td><td><tt>MultiIterator::reference</tt></td>
546  <td>access element at offset <tt>diff</tt></td>
547 </tr>
548 <tr>
549  <td><tt>i.dim<K>()</tt></td><td><tt>MultiIterator<K+1, T, ...></tt></td>
550  <td>Access the traverser with the current dimension set to K. Typically used to call
551  navigation functions referring to a particular dimension.<br>
552  Example (assuming <tt>i, j</tt> are 3-dimensional):<br>
553  \code
554  i.dim<0>()++; // increment dimension 0
555  i.dim<1>()++; // increment dimension 1
556  i.dim<2>()++; // increment dimension 2
557 
558  j += MultiIterator::multi_difference_type(1,1,1); // same effect
559  \endcode
560  </td>
561 </tr>
562 <tr><td colspan=3>
563  <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
564  <tt>diff</tt> is of type <tt>MultiIterator::multi_difference_type</tt><br>
565  <tt>K</tt> is an integer compile-time constant
566  </td>
567 </tr>
568 </table>
569 </p>
570 <p>
571 Note that it is impossible to support an <tt>operator-</tt> between two iterators which returns
572 a <tt>MultiIterator::multi_difference_type</tt> because it is impossible to decide to which
573 dimension a difference applies. Consider for example, a 2-dimensional iterator <tt>i</tt>, and
574 let <tt>j = i + multi_difference_type(width, 0)</tt>, <tt>k = i + multi_difference_type(0,1)</tt>,
575 where <tt>width</tt> is the array's total width. In general, <tt>j</tt> and <tt>k</tt> point to
576 the same memory location, so that the two cases cannot easily be distinguished (it is possible,
577 but iterator performance will suffer significantly, as is experienced with
578 \ref vigra::ImageIterator where differencing is allowed).
579 </p>
580 
581 <h3>Requirements for Hierarchical Traversal</h3>
582 <p>
583 <table border=2 cellspacing=0 cellpadding=2 width="100%">
584 <tr><th colspan=2>
585  Local Types
586  </th><th>
587  Meaning
588  </th>
589 </tr>
590 <tr><td colspan=2>
591  <tt>MultiIterator::difference_type</tt></td>
592  <td>the iterator's difference type (<TT>MultiArrayIndex</TT>)</td>
593 </tr>
594 <tr><td colspan=2>
595  <tt>MultiIterator::next_type</tt></td><td>type of the next iterator
596  (referring to the next lower dimension) in the hierarchy</td>
597 </tr>
598 <tr><th>
599  Operation
600  </th><th>
601  Result
602  </th><th>
603  Semantics
604  </th>
605 </tr>
606 <tr>
607  <td><tt>++i</tt></td><td><tt>MultiIterator &</tt></td>
608  <td>pre-increment iterator in its current dimension</td>
609 </tr>
610 <tr>
611  <td><tt>i++</tt></td><td><tt>MultiIterator</tt></td>
612  <td>post-increment iterator in its current dimension</td>
613 </tr>
614 <tr>
615  <td><tt>--i</tt></td><td><tt>MultiIterator &</tt></td>
616  <td>pre-decrement iterator in its current dimension</td>
617 </tr>
618 <tr>
619  <td><tt>i--</tt></td><td><tt>MultiIterator</tt></td>
620  <td>post-decrement iterator in its current dimension</td>
621 </tr>
622 <tr>
623  <td><tt>i += d</tt></td><td><tt>MultiIterator &</tt></td>
624  <td>add <tt>d</tt> in current dimension</td>
625 </tr>
626 <tr>
627  <td><tt>i -= d</tt></td><td><tt>MultiIterator &</tt></td>
628  <td>subtract <tt>d</tt> in from dimension</td>
629 </tr>
630 <tr>
631  <td><tt>i + d</tt></td><td><tt>MultiIterator</tt></td>
632  <td>create new iterator by adding <tt>d</tt> in current dimension</td>
633 </tr>
634 <tr>
635  <td><tt>i - d</tt></td><td><tt>MultiIterator</tt></td>
636  <td>create new iterator by subtracting <tt>d</tt> in current dimension</td>
637 </tr>
638 <tr>
639  <td><tt>i - j</tt></td><td><tt>difference_type</tt></td>
640  <td>difference of <tt>i</tt> and <tt>j</tt> in the current dimension<br>
641  <em>Note:</em> The result of this operation is undefined if the iterator
642  doesn't point to element 0 in all dimensions below its current dimension.</td>
643 </tr>
644 <tr>
645  <td><tt>i < j</tt></td><td><tt>bool</tt></td>
646  <td><tt>i - j < 0</tt><br>
647  <em>Note:</em> The result of this operation is undefined if the iterator
648  doesn't point to element 0 in all dimensions below its current dimension.</td>
649 </tr>
650 <tr>
651  <td><tt>i[d]</tt></td><td><tt>MultiIterator::reference</tt></td>
652  <td>access element by adding offset <tt>d</tt> in current dimension</td>
653 </tr>
654 <tr>
655  <td><tt>i.begin()</tt></td><td><tt>next_type</tt></td>
656  <td>create the hierarchical iterator pointing to the first element in the
657  next lower dimension.<br>
658  <em>Note:</em> The result of this operation is undefined if the iterator
659  doesn't point to element 0 in all dimensions below its current dimension.<br>
660  Usage:<br>
661  \code
662  MultiIterator<3, int> i3 = ..., end3 = ...;
663  for(; i3 != end3; ++i3)
664  {
665  MultiIterator<3, int>::next_type i2 = i3.begin(), end2 = i3.end();
666  for(; i2 != end2; ++i2)
667  {
668  MultiIterator<3, int>::next_type::next_type i1 = i2.begin(), end1 = i2.end();
669  for(; i1 != end1; ++i1)
670  {
671  ... // do something with the current element
672  }
673  }
674  }
675 
676  \endcode
677  </td>
678 </tr>
679 <tr>
680  <td><tt>i.end()</tt></td><td><tt>next_type</tt></td>
681  <td>create the hierarchical iterator pointing to the past-the-end location in the
682  next lower dimension.<br>
683  <em>Note:</em> The result of this operation is undefined if the iterator
684  doesn't point to element 0 in all dimensions below its current dimension.</td>
685 </tr>
686 <tr><td colspan=3>
687  <tt>i, j</tt> are of type <tt>MultiIterator</tt><br>
688  <tt>d</tt> is of type <tt>MultiIterator::difference_type</tt>
689  </td>
690 </tr>
691 </table>
692 </p>
693 
694 */
695 
696 /** \addtogroup MultiIteratorGroup
697 */
698 //@{
699 
700 template <class POINTER>
701 struct MultiIteratorStrideTraits
702 {
703  typedef MultiArrayIndex stride_type;
704  typedef const stride_type* stride_array_type;
705  typedef stride_array_type shape_array_type;
706  static stride_array_type shift(stride_array_type s, unsigned d)
707  {
708  return s + d;
709  }
710 };
711 
712 template <unsigned int N, class T, class REFERENCE = T &, class POINTER = T *>
714 
715 template <unsigned int N, class T, class REFERENCE = T &, class POINTER = T *>
717 
718 /********************************************************/
719 /* */
720 /* MultiIterator */
721 /* */
722 /********************************************************/
723 
724 /********************************************************/
725 /* */
726 /* MultiIterator<1> */
727 /* */
728 /********************************************************/
729 
730 //
731 template <class T, class REFERENCE, class POINTER>
733 {
734  public:
735  enum { level = 0 };
736  typedef T value_type;
737  typedef REFERENCE reference;
738  typedef const value_type &const_reference;
739  typedef POINTER pointer;
740  typedef const value_type *const_pointer;
742  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
743  typedef typename stride_traits::stride_type difference_type;
744  typedef typename stride_traits::stride_array_type difference_array_type;
745  typedef typename stride_traits::shape_array_type shape_array_type;
747  typedef std::random_access_iterator_tag iterator_category;
748 
749  protected:
750  pointer m_ptr;
751 
752  public:
753  MultiIterator ()
754  : m_ptr (0)
755  {}
756 
757  MultiIterator (pointer ptr,
758  const difference_array_type &,
759  const shape_array_type &)
760  : m_ptr (ptr)
761  {}
762 
763  void operator++ ()
764  {
765  ++m_ptr;
766  }
767 
768  void operator-- ()
769  {
770  --m_ptr;
771  }
772 
773  MultiIterator operator++ (int)
774  {
775  MultiIterator ret = *this;
776  ++(*this);
777  return ret;
778  }
779 
780  MultiIterator operator-- (int)
781  {
782  MultiIterator ret = *this;
783  --(*this);
784  return ret;
785  }
786 
787  MultiIterator &operator+= (difference_type n)
788  {
789  m_ptr += n;
790  return *this;
791  }
792 
793  MultiIterator & operator+= (multi_difference_type const & d)
794  {
795  m_ptr += d[level];
796  return *this;
797  }
798 
799  MultiIterator &operator-= (difference_type n)
800  {
801  m_ptr -= n;
802  return *this;
803  }
804 
805  MultiIterator & operator-= (multi_difference_type const & d)
806  {
807  m_ptr -= d[level];
808  return *this;
809  }
810 
811  MultiIterator operator+ (difference_type n) const
812  {
813  MultiIterator ret = *this;
814  ret += n;
815  return ret;
816  }
817 
818  MultiIterator operator+ (multi_difference_type const & d) const
819  {
820  MultiIterator ret = *this;
821  ret += d;
822  return ret;
823  }
824 
825  difference_type operator- (MultiIterator const & d) const
826  {
827  return (m_ptr - d.m_ptr);
828  }
829 
830  MultiIterator operator- (difference_type n) const
831  {
832  MultiIterator ret = *this;
833  ret -= n;
834  return ret;
835  }
836 
837  MultiIterator operator- (multi_difference_type const & d) const
838  {
839  MultiIterator ret = *this;
840  ret -= d;
841  return ret;
842  }
843 
844  reference operator[] (difference_type n) const
845  {
846  return m_ptr [n];
847  }
848 
849  reference operator[] (multi_difference_type const & d) const
850  {
851  return m_ptr [d[level]];
852  }
853 
854  reference operator* () const
855  {
856  return *m_ptr;
857  }
858 
859  pointer get () const
860  {
861  return m_ptr;
862  }
863 
864  pointer operator->() const
865  {
866  return &(operator*());
867  }
868 
869  bool operator!= (const MultiIterator &rhs) const
870  {
871  return m_ptr != rhs.m_ptr;
872  }
873 
874  bool operator== (const MultiIterator &rhs) const
875  {
876  return m_ptr == rhs.m_ptr;
877  }
878 
879  bool operator< (const MultiIterator &rhs) const
880  {
881  return m_ptr < rhs.m_ptr;
882  }
883 
884  bool operator<= (const MultiIterator &rhs) const
885  {
886  return m_ptr <= rhs.m_ptr;
887  }
888 
889  bool operator> (const MultiIterator &rhs) const
890  {
891  return m_ptr > rhs.m_ptr;
892  }
893 
894  bool operator>= (const MultiIterator &rhs) const
895  {
896  return m_ptr >= rhs.m_ptr;
897  }
898 
899  iterator iteratorForDimension(unsigned int d) const
900  {
901  vigra_precondition(d == 0,
902  "MultiIterator<1>::iteratorForDimension(d): d == 0 required");
903  const difference_type stride = 1;
904  return iterator(m_ptr, &stride, 0);
905  }
906 
907  template <unsigned int K>
909  dim()
910  {
911  return *this;
912  }
913 
915  dim0() { return *this; }
916 
917  protected:
918 
919  difference_type
920  total_stride(typename multi_difference_type::const_iterator d) const
921  {
922  return d[level];
923  }
924 };
925 
926 /********************************************************/
927 /* */
928 /* MultiIterator<2> */
929 /* */
930 /********************************************************/
931 
932 //
933 template <class T, class REFERENCE, class POINTER>
934 class MultiIterator<2, T, REFERENCE, POINTER>
935 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
936 : public MultiIterator<1, T, REFERENCE, POINTER>
937 #endif
938 {
939  public:
940 
942  enum { level = 1 };
943  typedef T value_type;
944  typedef REFERENCE reference;
945  typedef const value_type &const_reference;
946  typedef POINTER pointer;
947  typedef const value_type *const_pointer;
948  typedef typename MultiArrayShape<2>::type multi_difference_type;
949  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
950  typedef typename stride_traits::stride_type difference_type;
951  typedef typename stride_traits::stride_array_type difference_array_type;
952  typedef typename stride_traits::shape_array_type shape_array_type;
953  typedef base_type next_type;
954  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
955  typedef multi_dimensional_traverser_tag iterator_category;
956 
957  protected:
958  difference_array_type m_stride;
959  shape_array_type m_shape;
960 
961  public:
962  /* use default copy constructor and assignment operator */
963 
964  MultiIterator ()
965  : base_type (),
966  m_stride (0), m_shape (0)
967  {}
968 
969  MultiIterator (pointer ptr,
970  const difference_array_type & stride,
971  const shape_array_type & shape)
972  : base_type (ptr, stride, shape),
973  m_stride (stride), m_shape (shape)
974  {}
975 
976  void operator++ ()
977  {
978  this->m_ptr += m_stride [level];
979  }
980 
981  void operator-- ()
982  {
983  this->m_ptr -= m_stride [level];
984  }
985 
987  {
988  MultiIterator ret = *this;
989  ++(*this);
990  return ret;
991  }
992 
994  {
995  MultiIterator ret = *this;
996  --(*this);
997  return ret;
998  }
999 
1001  {
1002  this->m_ptr += n * m_stride [level];
1003  return *this;
1004  }
1005 
1007  {
1008  this->m_ptr += total_stride(d.begin());
1009  return *this;
1010  }
1011 
1013  {
1014  this->m_ptr -= n * m_stride [level];
1015  return *this;
1016  }
1017 
1019  {
1020  this->m_ptr -= total_stride(d.begin());
1021  return *this;
1022  }
1023 
1025  {
1026  MultiIterator ret = *this;
1027  ret += n;
1028  return ret;
1029  }
1030 
1032  {
1033  MultiIterator ret = *this;
1034  ret += d;
1035  return ret;
1036  }
1037 
1038  difference_type operator- (MultiIterator const & d) const
1039  {
1040  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1041  }
1042 
1044  {
1045  MultiIterator ret = *this;
1046  ret -= n;
1047  return ret;
1048  }
1049 
1051  {
1052  MultiIterator ret = *this;
1053  ret -= d;
1054  return ret;
1055  }
1056 
1058  {
1059  return this->m_ptr [n*m_stride [level]];
1060  }
1061 
1063  {
1064  return this->m_ptr [total_stride(d.begin())];
1065  }
1066 
1067  next_type begin () const
1068  {
1069  return *this;
1070  }
1071 
1072  next_type end () const
1073  {
1074  next_type ret = *this;
1075  ret += m_shape [level-1];
1076  return ret;
1077  }
1078 
1079  iterator iteratorForDimension(unsigned int d) const
1080  {
1081  vigra_precondition(d <= level,
1082  "MultiIterator<N>::iteratorForDimension(d): d < N required");
1083  return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
1084  }
1085 
1086  template <unsigned int K>
1087  MultiIterator<K+1, T, REFERENCE, POINTER> &
1088  dim()
1089  {
1090  return *this;
1091  }
1092 
1093  MultiIterator<1, T, REFERENCE, POINTER> &
1094  dim0() { return *this; }
1095  MultiIterator<2, T, REFERENCE, POINTER> &
1096  dim1() { return *this; }
1097 
1098  protected:
1099 
1101  total_stride(typename multi_difference_type::const_iterator d) const
1102  {
1103  return d[level]*m_stride[level] + base_type::total_stride(d);
1104  }
1105 };
1106 
1107 /********************************************************/
1108 /* */
1109 /* MultiIterator<N> */
1110 /* */
1111 /********************************************************/
1112 
1113 /** \brief A multi-dimensional hierarchical iterator to be used with
1114  \ref vigra::MultiArrayView if it is not strided.
1115 
1116  See \ref MultiIteratorPage for further documentation.
1117 
1118  <b>\#include</b> <vigra/multi_iterator.hxx> <br>
1119  Namespace: vigra
1120 */
1121 template <unsigned int N, class T, class REFERENCE, class POINTER>
1122 class MultiIterator
1123 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1124 : public MultiIterator<N-1, T, REFERENCE, POINTER>
1125 #endif
1126 {
1127 public:
1128 
1129  /** the type of the parent in the inheritance hierarchy.
1130  */
1131  typedef MultiIterator<N-1, T, REFERENCE, POINTER> base_type;
1132 
1133  /** the iterator's level in the dimension hierarchy
1134  */
1135  enum { level = N-1 };
1136 
1137  /** the iterator's value type
1138  */
1139  typedef T value_type;
1140 
1141  /** reference type (result of operator[])
1142  */
1143  typedef REFERENCE reference;
1144 
1145  /** const reference type (result of operator[] const)
1146  */
1147  typedef const value_type &const_reference;
1148 
1149  /** pointer type
1150  */
1151  typedef POINTER pointer;
1152 
1153  /** const pointer type
1154  */
1155  typedef const value_type *const_pointer;
1156 
1157  /** multi difference type
1158  (used for offsetting along all axes simultaneously)
1159  */
1161 
1162  /** difference type (used for offsetting)
1163  */
1164 #ifndef DOXYGEN
1165  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1166  typedef typename stride_traits::stride_type difference_type;
1167  typedef typename stride_traits::stride_array_type difference_array_type;
1168  typedef typename stride_traits::shape_array_type shape_array_type;
1169 #else
1171 #endif
1172 
1173  /** the MultiIterator for the next lower dimension.
1174  */
1176 
1177  /** the 1-dimensional iterator for this iterator hierarchy
1178  (result of iteratorForDimension()).
1179  */
1181 
1182  /** the iterator tag (image traverser)
1183  */
1184  typedef multi_dimensional_traverser_tag iterator_category;
1185 
1186  /* use default copy constructor and assignment operator */
1187 
1188  /** default constructor.
1189  */
1191  {}
1192 
1193  /** construct from pointer, strides (offset of a sample to the
1194  next) for every dimension, and the shape.
1195  */
1197  const difference_array_type & stride,
1198  const shape_array_type & shape)
1199  : base_type (ptr, stride, shape)
1200  {}
1201 
1202 
1203  /** prefix-increment the iterator in its current dimension
1204  */
1206  {
1207  this->m_ptr += this->m_stride [level];
1208  }
1209 
1210  /** prefix-decrement the iterator in its current dimension
1211  */
1213  {
1214  this->m_ptr -= this->m_stride [level];
1215  }
1216 
1217  /** postfix-increment the iterator in its current dimension
1218  */
1220  {
1221  MultiIterator ret = *this;
1222  ++(*this);
1223  return ret;
1224  }
1225 
1226  /** postfix-decrement the iterator in its current dimension
1227  */
1229  {
1230  MultiIterator ret = *this;
1231  --(*this);
1232  return ret;
1233  }
1234 
1235  /** increment the iterator in its current dimension
1236  by the given value.
1237  */
1239  {
1240  this->m_ptr += n * this->m_stride [level];
1241  return *this;
1242  }
1243 
1244  /** increment the iterator in all dimensions
1245  by the given offset.
1246  */
1248  {
1249  this->m_ptr += total_stride(d.begin());
1250  return *this;
1251  }
1252 
1253  /** decrement the iterator in its current dimension
1254  by the given value.
1255  */
1257  {
1258  this->m_ptr -= n * this->m_stride [level];
1259  return *this;
1260  }
1261 
1262  /** decrement the iterator in all dimensions
1263  by the given offset.
1264  */
1266  {
1267  this->m_ptr -= total_stride(d.begin());
1268  return *this;
1269  }
1270 
1271  /** addition within current dimension
1272  */
1274  {
1275  MultiIterator ret = *this;
1276  ret += n;
1277  return ret;
1278  }
1279 
1280  /** addition along all dimensions
1281  */
1283  {
1284  MultiIterator ret = *this;
1285  ret += d;
1286  return ret;
1287  }
1288 
1289  /** difference of two iterators in the current dimension.
1290  The result of this operation is undefined if the iterator
1291  doesn't point to element 0 in all dimensions below its current dimension.
1292  */
1294  {
1295  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1296  }
1297 
1298  /** subtraction within current dimension
1299  */
1301  {
1302  MultiIterator ret = *this;
1303  ret -= n;
1304  return ret;
1305  }
1306 
1307  /** subtraction along all dimensions
1308  */
1310  {
1311  MultiIterator ret = *this;
1312  ret -= d;
1313  return ret;
1314  }
1315 
1316 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
1317  /** derefenrence item
1318  */
1319  reference operator* () const;
1320 
1321  /** get address of current item
1322  */
1323  pointer get () const;
1324 
1325  /** call method of current item
1326  */
1327  pointer operator->() const;
1328 
1329  /** inequality. True if iterators reference different items.
1330  */
1331  bool operator!= (const MultiIterator &rhs) const;
1332 
1333  /** equality. True if iterators reference the same items.
1334  */
1335  bool operator== (const MultiIterator &rhs) const;
1336 
1337  /** less than.
1338  */
1339  bool operator< (const MultiIterator &rhs) const;
1340 
1341  /** less or equal.
1342  */
1343  bool operator<= (const MultiIterator &rhs) const;
1344 
1345  /** greater than.
1346  */
1347  bool operator> (const MultiIterator &rhs) const;
1348 
1349  /** greater or equal.
1350  */
1351  bool operator>= (const MultiIterator &rhs) const;
1352 #endif
1353 
1354  /** access the array element at the given offset in
1355  the current dimension.
1356  */
1358  {
1359  return this->m_ptr [n* this->m_stride [level]];
1360  }
1361 
1362  /** access the array element at the given offset.
1363  */
1365  {
1366  return this->m_ptr [total_stride(d.begin())];
1367  }
1368 
1369  /** Return the (N-1)-dimensional multi-iterator that points to
1370  the first (N-1)-dimensional subarray of the
1371  N-dimensional array this iterator is referring to.
1372  The result is only valid if this iterator refers to location
1373  0 in <em>all</em> dimensions below its current dimension N,
1374  otherwise it is undefined. Usage:
1375 
1376  \code
1377 
1378  MultiIterator<2, int> outer = ...; // this iterator
1379 
1380  MultiIterator<2, int>::next_type inner = outer.begin();
1381  for(; inner != outer.end(); ++inner)
1382  {
1383  // manipulate current 1D subimage
1384  }
1385  \endcode
1386  */
1387  next_type begin () const
1388  {
1389  return *this;
1390  }
1391 
1392  /** Return the (N-1)-dimensional multi-iterator that points beyond
1393  the last (N-1)-dimensional subarray of the
1394  N-dimensional array this iterator is referring to.
1395  The result is only valid if this iterator refers to location
1396  0 in <em>all</em> dimensions below its current dimension N,
1397  otherwise it is undefined.
1398  */
1399  next_type end () const
1400  {
1401  next_type ret = *this;
1402  ret += this->m_shape [level-1];
1403  return ret;
1404  }
1405 
1406  /** Get a 1-dimensional, STL-compatible iterator for the
1407  given dimension, pointing to the current element of <TT>this</TT>.
1408  Usage:
1409 
1410  \code
1411 
1412  MultiIterator<3, int> outer = ...; // this iterator
1413 
1414  MultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
1415  MultiIterator<3, int>::iterator end = i + height;
1416  for(; i != end; ++i)
1417  {
1418  // go down the current column starting at the location of 'outer'
1419  }
1420  \endcode
1421  */
1422  iterator iteratorForDimension(unsigned int d) const
1423  {
1424  vigra_precondition(d <= level,
1425  "MultiIterator<N>::iteratorForDimension(d): d < N required");
1426  return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d),0);
1427  }
1428  /** Return the multi-iterator that operates on dimension K in order
1429  to manipulate this dimension directly. Usage:
1430 
1431  \code
1432 
1433  MultiIterator<3, int> i3 = ...;
1434 
1435  i3.template dim<2>()++; // increment outer dimension
1436  i3.template dim<0>()++; // increment inner dimension
1437  \endcode
1438 
1439  For convenience, the same functionality is also available
1440  as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
1441 
1442  \code
1443 
1444  MultiIterator<3, int> i3 = ...;
1445 
1446  i3.dim2()++; // increment outer dimension
1447  i3.dim0()++; // increment inner dimension
1448  \endcode
1449  */
1450  template <unsigned int K>
1453  {
1454  return *this;
1455  }
1456 
1458  dim0() { return *this; }
1459  MultiIterator<2, T, REFERENCE, POINTER> &
1460  dim1() { return *this; }
1461  MultiIterator<3, T, REFERENCE, POINTER> &
1462  dim2() { return *this; }
1463  MultiIterator<4, T, REFERENCE, POINTER> &
1464  dim3() { return *this; }
1465  MultiIterator<5, T, REFERENCE, POINTER> &
1466  dim4() { return *this; }
1467 
1468  protected:
1469 
1471  total_stride(typename multi_difference_type::const_iterator d) const
1472  {
1473  return d[level]*this->m_stride[level] + base_type::total_stride(d);
1474  }
1475 
1476 };
1477 
1478 /********************************************************/
1479 /* */
1480 /* StridedMultiIterator */
1481 /* */
1482 /********************************************************/
1483 
1484 /********************************************************/
1485 /* */
1486 /* StridedMultiIterator<1> */
1487 /* */
1488 /********************************************************/
1489 
1490 //
1491 template <class T, class REFERENCE, class POINTER>
1492 class StridedMultiIterator<1, T, REFERENCE, POINTER>
1493 {
1494  public:
1495  enum { level = 0 };
1496  typedef T value_type;
1497  typedef REFERENCE reference;
1498  typedef const value_type &const_reference;
1499  typedef POINTER pointer;
1500  typedef const value_type *const_pointer;
1501  typedef typename MultiArrayShape<1>::type multi_difference_type;
1502  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1503  typedef typename stride_traits::stride_type difference_type;
1504  typedef typename stride_traits::stride_array_type difference_array_type;
1505  typedef typename stride_traits::shape_array_type shape_array_type;
1506  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1507  typedef std::random_access_iterator_tag iterator_category;
1508 
1509  protected:
1510  pointer m_ptr;
1511  difference_type m_stride;
1512 
1513  /* use default copy constructor and assignment operator */
1514 
1515  public:
1517  : m_ptr (0), m_stride (0)
1518  {}
1519 
1521  const difference_array_type & stride,
1522  const shape_array_type &)
1523  : m_ptr (ptr), m_stride (stride [level])
1524  {}
1525 
1526  void operator++ ()
1527  {
1528  m_ptr += m_stride;
1529  }
1530 
1531  void operator-- ()
1532  {
1533  m_ptr -= m_stride;
1534  }
1535 
1537  {
1538  StridedMultiIterator ret = *this;
1539  ++(*this);
1540  return ret;
1541  }
1542 
1544  {
1545  StridedMultiIterator ret = *this;
1546  --(*this);
1547  return ret;
1548  }
1549 
1551  {
1552  m_ptr += n * m_stride;
1553  return *this;
1554  }
1555 
1557  {
1558  m_ptr += d[level] * m_stride;
1559  return *this;
1560  }
1561 
1563  {
1564  m_ptr -= n * m_stride;
1565  return *this;
1566  }
1567 
1569  {
1570  m_ptr -= d[level] * m_stride;
1571  return *this;
1572  }
1573 
1575  {
1576  StridedMultiIterator ret = *this;
1577  ret += n;
1578  return ret;
1579  }
1580 
1582  {
1583  StridedMultiIterator ret = *this;
1584  ret += d;
1585  return ret;
1586  }
1587 
1589  {
1590  return (m_ptr - d.m_ptr) / m_stride;
1591  }
1592 
1594  {
1595  StridedMultiIterator ret = *this;
1596  ret -= n;
1597  return ret;
1598  }
1599 
1601  {
1602  StridedMultiIterator ret = *this;
1603  ret -= d;
1604  return ret;
1605  }
1606 
1608  {
1609  return m_ptr [n*m_stride];
1610  }
1611 
1613  {
1614  return m_ptr [d[level]*m_stride];
1615  }
1616 
1617  reference operator* () const
1618  {
1619  return *m_ptr;
1620  }
1621 
1622  pointer get () const
1623  {
1624  return m_ptr;
1625  }
1626 
1627  pointer operator->() const
1628  {
1629  return &(operator*());
1630  }
1631 
1632  bool operator!= (const StridedMultiIterator &rhs) const
1633  {
1634  return m_ptr != rhs.m_ptr;
1635  }
1636 
1637  bool operator== (const StridedMultiIterator &rhs) const
1638  {
1639  return m_ptr == rhs.m_ptr;
1640  }
1641 
1642  bool operator< (const StridedMultiIterator &rhs) const
1643  {
1644  return m_ptr < rhs.m_ptr;
1645  }
1646 
1647  bool operator<= (const StridedMultiIterator &rhs) const
1648  {
1649  return m_ptr <= rhs.m_ptr;
1650  }
1651 
1652  bool operator> (const StridedMultiIterator &rhs) const
1653  {
1654  return m_ptr > rhs.m_ptr;
1655  }
1656 
1657  bool operator>= (const StridedMultiIterator &rhs) const
1658  {
1659  return m_ptr >= rhs.m_ptr;
1660  }
1661 
1662  iterator iteratorForDimension(unsigned int d) const
1663  {
1664  vigra_precondition(d == 0,
1665  "StridedMultiIterator<1>::iteratorForDimension(d): d == 0 required");
1666  const difference_type stride = 1;
1667  return iterator(m_ptr, &stride, 0);
1668  }
1669 
1670  template <unsigned int K>
1671  StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1672  dim()
1673  {
1674  return *this;
1675  }
1676 
1677  StridedMultiIterator<1, T, REFERENCE, POINTER> &
1678  dim0() { return *this; }
1679 
1680  protected:
1681 
1683  total_stride(typename multi_difference_type::const_iterator d) const
1684  {
1685  return d[level] * m_stride;
1686  }
1687 };
1688 
1689 /********************************************************/
1690 /* */
1691 /* StridedMultiIterator<2> */
1692 /* */
1693 /********************************************************/
1694 
1695 //
1696 template <class T, class REFERENCE, class POINTER>
1697 class StridedMultiIterator<2, T, REFERENCE, POINTER>
1698 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1699 : public StridedMultiIterator<1, T, REFERENCE, POINTER>
1700 #endif
1701 {
1702  public:
1703 
1704  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> base_type;
1705  enum { level = 1 };
1706  typedef T value_type;
1707  typedef REFERENCE reference;
1708  typedef const value_type &const_reference;
1709  typedef POINTER pointer;
1710  typedef const value_type *const_pointer;
1711  typedef typename MultiArrayShape<2>::type multi_difference_type;
1712  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1713  typedef typename stride_traits::stride_type difference_type;
1714  typedef typename stride_traits::stride_array_type difference_array_type;
1715  typedef typename stride_traits::shape_array_type shape_array_type;
1716  typedef base_type next_type;
1717  typedef StridedMultiIterator<1, T, REFERENCE, POINTER> iterator;
1718  typedef multi_dimensional_traverser_tag iterator_category;
1719 
1720  protected:
1721  difference_array_type m_stride;
1722  shape_array_type m_shape;
1723 
1724  public:
1725  /* use default copy constructor and assignment operator */
1726 
1728  : base_type (),
1729  m_stride (0), m_shape (0)
1730  {}
1731 
1733  const difference_array_type & stride,
1734  const shape_array_type & shape)
1735  : base_type (ptr, stride, shape),
1736  m_stride (stride), m_shape (shape)
1737  {}
1738 
1739  void operator++ ()
1740  {
1741  this->m_ptr += m_stride [level];
1742  }
1743 
1744  void operator-- ()
1745  {
1746  this->m_ptr -= m_stride [level];
1747  }
1748 
1750  {
1751  StridedMultiIterator ret = *this;
1752  ++(*this);
1753  return ret;
1754  }
1755 
1757  {
1758  StridedMultiIterator ret = *this;
1759  --(*this);
1760  return ret;
1761  }
1762 
1764  {
1765  this->m_ptr += n * m_stride [level];
1766  return *this;
1767  }
1768 
1770  {
1771  this->m_ptr += total_stride(d.begin());
1772  return *this;
1773  }
1774 
1776  {
1777  this->m_ptr -= n * m_stride [level];
1778  return *this;
1779  }
1780 
1782  {
1783  this->m_ptr -= total_stride(d.begin());
1784  return *this;
1785  }
1786 
1788  {
1789  StridedMultiIterator ret = *this;
1790  ret += n;
1791  return ret;
1792  }
1793 
1795  {
1796  StridedMultiIterator ret = *this;
1797  ret += d;
1798  return ret;
1799  }
1800 
1802  {
1803  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
1804  }
1805 
1807  {
1808  StridedMultiIterator ret = *this;
1809  ret -= n;
1810  return ret;
1811  }
1812 
1814  {
1815  StridedMultiIterator ret = *this;
1816  ret -= d;
1817  return ret;
1818  }
1819 
1821  {
1822  return this->m_ptr [n*m_stride [level]];
1823  }
1824 
1826  {
1827  return this->m_ptr [total_stride(d.begin())];
1828  }
1829 
1830  next_type begin () const
1831  {
1832  return *this;
1833  }
1834 
1835  next_type end () const
1836  {
1837  next_type ret = *this;
1838  ret += m_shape [level-1];
1839  return ret;
1840  }
1841 
1842  iterator iteratorForDimension(unsigned int d) const
1843  {
1844  vigra_precondition(d <= level,
1845  "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
1846  return iterator(this->m_ptr, stride_traits::shift(m_stride, d), 0);
1847  }
1848 
1849  template <unsigned int K>
1850  StridedMultiIterator<K+1, T, REFERENCE, POINTER> &
1851  dim()
1852  {
1853  return *this;
1854  }
1855 
1856  StridedMultiIterator<1, T, REFERENCE, POINTER> &
1857  dim0() { return *this; }
1858  StridedMultiIterator<2, T, REFERENCE, POINTER> &
1859  dim1() { return *this; }
1860 
1861  protected:
1862 
1864  total_stride(typename multi_difference_type::const_iterator d) const
1865  {
1866  return d[level]*m_stride[level] + base_type::total_stride(d);
1867  }
1868 };
1869 
1870 /********************************************************/
1871 /* */
1872 /* StridedMultiIterator<N> */
1873 /* */
1874 /********************************************************/
1875 
1876 /** \brief A multi-dimensional hierarchical iterator to be used with
1877  \ref vigra::MultiArrayView if it is not strided.
1878 
1879  See \ref MultiIteratorPage for further documentation.
1880 
1881  <b>\#include</b> <vigra/multi_iterator.hxx> <br>
1882  Namespace: vigra
1883 */
1884 template <unsigned int N, class T, class REFERENCE, class POINTER>
1885 class StridedMultiIterator
1886 #ifndef DOXYGEN // doxygen doesn't understand this inheritance
1887 : public StridedMultiIterator<N-1, T, REFERENCE, POINTER>
1888 #endif
1889 {
1890 public:
1891 
1892  /** the type of the parent in the inheritance hierarchy.
1893  */
1894  typedef StridedMultiIterator<N-1, T, REFERENCE, POINTER> base_type;
1895 
1896  /** the iterator's level in the dimension hierarchy
1897  */
1898  enum { level = N-1 };
1899 
1900  /** the iterator's value type
1901  */
1902  typedef T value_type;
1903 
1904  /** reference type (result of operator[])
1905  */
1906  typedef REFERENCE reference;
1907 
1908  /** const reference type (result of operator[] const)
1909  */
1910  typedef const value_type &const_reference;
1911 
1912  /** pointer type
1913  */
1914  typedef POINTER pointer;
1915 
1916  /** const pointer type
1917  */
1918  typedef const value_type *const_pointer;
1919 
1920  /** multi difference type
1921  (used for offsetting along all axes simultaneously)
1922  */
1924 
1925  /** difference type (used for offsetting)
1926  */
1927 #ifndef DOXYGEN
1928  typedef MultiIteratorStrideTraits<POINTER> stride_traits;
1929  typedef typename stride_traits::stride_type difference_type;
1930  typedef typename stride_traits::stride_array_type difference_array_type;
1931 #else
1933 #endif
1934 
1935  /** the StridedMultiIterator for the next lower dimension.
1936  */
1938 
1939  /** the 1-dimensional iterator for this iterator hierarchy
1940  (result of iteratorForDimension()).
1941  */
1943 
1944  /** the iterator tag (image traverser)
1945  */
1946  typedef multi_dimensional_traverser_tag iterator_category;
1947 
1948  /* use default copy constructor and assignment operator */
1949 
1950  /** default constructor.
1951  */
1953  {}
1954 
1955  /** construct from pointer, strides (offset of a sample to the
1956  next) for every dimension, and the shape.
1957  */
1959  const difference_array_type & stride,
1960  const difference_array_type & shape)
1961  : base_type (ptr, stride, shape)
1962  {}
1963 
1964 
1965  /** prefix-increment the iterator in its current dimension
1966  */
1968  {
1969  this->m_ptr += this->m_stride [level];
1970  }
1971 
1972  /** prefix-decrement the iterator in its current dimension
1973  */
1975  {
1976  this->m_ptr -= this->m_stride [level];
1977  }
1978 
1979  /** postfix-increment the iterator in its current dimension
1980  */
1982  {
1983  StridedMultiIterator ret = *this;
1984  ++(*this);
1985  return ret;
1986  }
1987 
1988  /** postfix-decrement the iterator in its current dimension
1989  */
1991  {
1992  StridedMultiIterator ret = *this;
1993  --(*this);
1994  return ret;
1995  }
1996 
1997  /** increment the iterator in its current dimension
1998  by the given value.
1999  */
2001  {
2002  this->m_ptr += n * this->m_stride [level];
2003  return *this;
2004  }
2005 
2006  /** increment the iterator in all dimensions
2007  by the given offset.
2008  */
2010  {
2011  this->m_ptr += total_stride(d.begin());
2012  return *this;
2013  }
2014 
2015  /** decrement the iterator in its current dimension
2016  by the given value.
2017  */
2019  {
2020  this->m_ptr -= n * this->m_stride [level];
2021  return *this;
2022  }
2023 
2024  /** decrement the iterator in all dimensions
2025  by the given offset.
2026  */
2028  {
2029  this->m_ptr -= total_stride(d.begin());
2030  return *this;
2031  }
2032 
2033  /** addition within current dimension
2034  */
2036  {
2037  StridedMultiIterator ret = *this;
2038  ret += n;
2039  return ret;
2040  }
2041 
2042  /** addition along all dimensions
2043  */
2045  {
2046  StridedMultiIterator ret = *this;
2047  ret += d;
2048  return ret;
2049  }
2050 
2051  /** difference of two iterators in the current dimension.
2052  The result of this operation is undefined if the iterator
2053  doesn't point to element 0 in all dimensions below its current dimension.
2054  */
2056  {
2057  return (this->m_ptr - d.m_ptr) / this->m_stride[level];
2058  }
2059 
2060  /** subtraction within current dimension
2061  */
2063  {
2064  StridedMultiIterator ret = *this;
2065  ret -= n;
2066  return ret;
2067  }
2068 
2069  /** subtraction along all dimensions
2070  */
2072  {
2073  StridedMultiIterator ret = *this;
2074  ret -= d;
2075  return ret;
2076  }
2077 
2078 #ifdef DOXYGEN /* documentation only: operators *, ->, ==, !=, <, <=, >, >= are inherited */
2079  /** derefenrence item
2080  */
2081  reference operator* () const;
2082 
2083  /** get address of current item
2084  */
2085  pointer get () const;
2086 
2087  /** call method of current item
2088  */
2089  pointer operator->() const;
2090 
2091  /** inequality. True if iterators reference different items.
2092  */
2093  bool operator!= (const StridedMultiIterator &rhs) const;
2094 
2095  /** equality. True if iterators reference the same items.
2096  */
2097  bool operator== (const StridedMultiIterator &rhs) const;
2098 
2099  /** less than.
2100  */
2101  bool operator< (const StridedMultiIterator &rhs) const;
2102 
2103  /** less or equal.
2104  */
2105  bool operator<= (const StridedMultiIterator &rhs) const;
2106 
2107  /** greater than.
2108  */
2109  bool operator> (const StridedMultiIterator &rhs) const;
2110 
2111  /** greater or equal.
2112  */
2113  bool operator>= (const StridedMultiIterator &rhs) const;
2114 #endif
2115 
2116  /** access the array element at the given offset in
2117  the current dimension.
2118  */
2120  {
2121  return this->m_ptr [n* this->m_stride [level]];
2122  }
2123 
2124  /** access the array element at the given offset.
2125  */
2127  {
2128  return this->m_ptr [total_stride(d.begin())];
2129  }
2130 
2131  /** Return the (N-1)-dimensional multi-iterator that points to
2132  the first (N-1)-dimensional subarray of the
2133  N-dimensional array this iterator is referring to.
2134  The result is only valid if this iterator refers to location
2135  0 in <em>all</em> dimensions below its current dimension N,
2136  otherwise it is undefined. Usage:
2137 
2138  \code
2139 
2140  StridedMultiIterator<2, int> outer = ...; // this iterator
2141 
2142  StridedMultiIterator<2, int>::next_type inner = outer.begin();
2143  for(; inner != outer.end(); ++inner)
2144  {
2145  // manipulate current 1D subimage
2146  }
2147  \endcode
2148  */
2149  next_type begin () const
2150  {
2151  return *this;
2152  }
2153 
2154  /** Return the (N-1)-dimensional multi-iterator that points beyond
2155  the last (N-1)-dimensional subarray of the
2156  N-dimensional array this iterator is referring to.
2157  The result is only valid if this iterator refers to location
2158  0 in <em>all</em> dimensions below its current dimension N,
2159  otherwise it is undefined.
2160  */
2161  next_type end () const
2162  {
2163  next_type ret = *this;
2164  ret += this->m_shape [level-1];
2165  return ret;
2166  }
2167 
2168  /** Get a 1-dimensional, STL-compatible iterator for the
2169  given dimension, pointing to the current element of <TT>this</TT>.
2170  Usage:
2171 
2172  \code
2173 
2174  StridedMultiIterator<3, int> outer = ...; // this iterator
2175 
2176  StridedMultiIterator<3, int>::iterator i = outer.iteratorForDimension(1);
2177  StridedMultiIterator<3, int>::iterator end = i + height;
2178  for(; i != end; ++i)
2179  {
2180  // go down the current column starting at the location of 'outer'
2181  }
2182  \endcode
2183  */
2184  iterator iteratorForDimension(unsigned int d) const
2185  {
2186  vigra_precondition(d <= level,
2187  "StridedMultiIterator<N>::iteratorForDimension(d): d < N required");
2188  return iterator(this->m_ptr, stride_traits::shift(this->m_stride, d),0);
2189  }
2190  /** Return the multi-iterator that operates on dimension K in order
2191  to manipulate this dimension directly. Usage:
2192 
2193  \code
2194 
2195  StridedMultiIterator<3, int> i3 = ...;
2196 
2197  i3.template dim<2>()++; // increment outer dimension
2198  i3.template dim<0>()++; // increment inner dimension
2199  \endcode
2200 
2201  For convenience, the same functionality is also available
2202  as <tt>dim0()</tt>, <tt>dim1()</tt> etc. up to <tt>dim4()</tt>:
2203 
2204  \code
2205 
2206  StridedMultiIterator<3, int> i3 = ...;
2207 
2208  i3.dim2()++; // increment outer dimension
2209  i3.dim0()++; // increment inner dimension
2210  \endcode
2211  */
2212  template <unsigned int K>
2215  {
2216  return *this;
2217  }
2218 
2220  dim0() { return *this; }
2221  StridedMultiIterator<2, T, REFERENCE, POINTER> &
2222  dim1() { return *this; }
2223  StridedMultiIterator<3, T, REFERENCE, POINTER> &
2224  dim2() { return *this; }
2225  StridedMultiIterator<4, T, REFERENCE, POINTER> &
2226  dim3() { return *this; }
2227  StridedMultiIterator<5, T, REFERENCE, POINTER> &
2228  dim4() { return *this; }
2229 
2230  protected:
2231 
2233  total_stride(typename multi_difference_type::const_iterator d) const
2234  {
2235  return d[level]*this->m_stride[level] + base_type::total_stride(d);
2236  }
2237 
2238 };
2239 
2240 //@}
2241 
2242 } // namespace vigra
2243 
2244 namespace std {
2245 
2246 template <unsigned int N, class T, class REFERENCE, class POINTER>
2247 ostream & operator<<(ostream & o, vigra::StridedScanOrderIterator<N, T, REFERENCE, POINTER> const & i)
2248 {
2249  o << *i;
2250  return o;
2251 }
2252 
2253 } // namespace std
2254 
2255 #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.10.0