* mln/core/internal/complex_iter_base.hh: New.
* mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
Remove.
(mln::internal::complex_fwd_iter_<D>)
(mln::internal::complex_bkd_iter_<D>):
Inherit from mln::internal::complex_iter_base_.
Adjust.
* mln/core/faces_iter.hh (mln::internal::faces_iter_<N, D, E>):
Remove.
(mln::internal::faces_fwd_iter_<N, D>)
(mln::internal::faces_bkd_iter_<N, D>):
Inherit from mln::internal::complex_iter_base_.
Adjust.
* mln/core/face.hh (mln::face_handle<N, D>::n): New accessor.
(mln::face_handle<N, D>::complex_type)
(mln::any_face_handle<D>::complex_type):
New typedefs.
(mln::face_handle<N, D>::invalidate)
(mln::any_face_handle<D>::invalidate):
New methods.
---
milena/ChangeLog | 25 +++
milena/mln/core/complex_iter.hh | 219 ++----------------------
milena/mln/core/face.hh | 35 ++++
milena/mln/core/faces_iter.hh | 215 ++----------------------
milena/mln/core/internal/complex_iter_base.hh | 214 ++++++++++++++++++++++++
5 files changed, 310 insertions(+), 398 deletions(-)
create mode 100644 milena/mln/core/internal/complex_iter_base.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f164de6..f4629b7 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,30 @@
2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+ Factor (more) iterators on complexes and faces.
+
+ * mln/core/internal/complex_iter_base.hh: New.
+ * mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
+ Remove.
+ (mln::internal::complex_fwd_iter_<D>)
+ (mln::internal::complex_bkd_iter_<D>):
+ Inherit from mln::internal::complex_iter_base_.
+ Adjust.
+ * mln/core/faces_iter.hh (mln::internal::faces_iter_<N, D, E>):
+ Remove.
+ (mln::internal::faces_fwd_iter_<N, D>)
+ (mln::internal::faces_bkd_iter_<N, D>):
+ Inherit from mln::internal::complex_iter_base_.
+ Adjust.
+ * mln/core/face.hh (mln::face_handle<N, D>::n): New accessor.
+ (mln::face_handle<N, D>::complex_type)
+ (mln::any_face_handle<D>::complex_type):
+ New typedefs.
+ (mln::face_handle<N, D>::invalidate)
+ (mln::any_face_handle<D>::invalidate):
+ New methods.
+
+2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+
Add iterators on the n-faces of a complex.
* mln/core/faces_iter.hh: New.
diff --git a/milena/mln/core/complex_iter.hh b/milena/mln/core/complex_iter.hh
index 4aa9b99..3dcb445 100644
--- a/milena/mln/core/complex_iter.hh
+++ b/milena/mln/core/complex_iter.hh
@@ -31,95 +31,11 @@
/// \file mln/core/complex_iter.hh
/// \brief Definition of forward and backward iterators on complexes.
-# include <limits>
-
-# include <mln/core/concept/iterator.hh>
-# include <mln/core/complex.hh>
+# include <mln/core/internal/complex_iter_base.hh>
namespace mln
{
- // Fwd decls.
- template <unsigned D> class complex;
-
- /*--------------------------------.
- | internal::complex_iter_<D, E>. |
- `--------------------------------*/
-
- namespace internal
- {
- /// \brief Factoring classe for iterators on all the faces of
- /// a mln::complex<D>.
- ///
- /// \arg \p D The dimension of the complex this iterator belongs to.
- /// \arg \p E The type exact type of the iterator.
- template <unsigned D, typename E>
- class complex_iter_ : public Iterator<E>
- {
- typedef complex_iter_<D, E> self_;
-
- public:
- typedef any_face_handle<D> face;
-
- /// Construction and assignment.
- /// \{
- complex_iter_();
- /* FIXME: Keep this non-const? See a (big) comment about this in
- milena/tests/complex_image.cc. */
- complex_iter_(complex<D>& c);
- complex_iter_(const self_& rhs);
- self_& operator= (const self_& rhs);
- /// \}
-
- /// Manipulation.
- /// \{
- /// Test if the iterator is valid.
- bool is_valid() const;
- /// Invalidate the iterator.
- void invalidate();
- /// \}
-
- /// Conversion and accessors.
- /// \{
- /// Reference to the corresponding any-face handle.
- const face& to_face () const;
- /// Convert the iterator into an any-face handle.
- operator face() const;
- /// \}
-
- protected:
- /// The face handle this iterator is pointing to.
- face face_;
-
- private:
- /// \brief An invalid value for both the dimension and the id of
- /// the face.
- ///
- /// Use a function instead of a static constant, since `static'
- /// variables needs to be compiled once, which requires a compiled
- /// library to avoid duplicate symbols, which is something that
- /// was not really planned in Milena. A function tagged `inlined'
- /// can appear multiple times in a program, and solves this
- /// problem. We rely on the compiler to inline this call.
- ///
- /// Of course, we could have used UINT_MAX, but it is not very
- /// C++.
- unsigned invalid_unsigned_() const;
- };
-
-
- /* FIXME: This hand-made delegation is painful. We should rely on
- the general mechanism provided by Point_Site. But then again, we
- need to refine/adjust the interface of Point_Site w.r.t. the
- mandatory conversions to points. */
- template <unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_iter_<D, E>& p);
-
- } // end of mln::internal
-
-
/*-----------------------.
| complex_fwd_iter_<D>. |
`-----------------------*/
@@ -129,10 +45,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned D>
class complex_fwd_iter_
- : public internal::complex_iter_< D, complex_fwd_iter_<D> >
+ : public internal::complex_iter_base_< any_face_handle<D>,
+ complex_fwd_iter_<D> >
{
+ public:
+ typedef any_face_handle<D> face;
+
+ private:
typedef complex_fwd_iter_<D> self_;
- typedef internal::complex_iter_< D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -142,7 +63,7 @@ namespace mln
/// Construction and assignment.
/// \{
complex_fwd_iter_();
- // FIXME: See above (internal::complex_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
complex_fwd_iter_(complex<D>& c);
complex_fwd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -174,10 +95,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned D>
class complex_bkd_iter_
- : public internal::complex_iter_< D, complex_bkd_iter_<D> >
+ : public internal::complex_iter_base_< any_face_handle<D>,
+ complex_bkd_iter_<D> >
{
+ public:
+ typedef any_face_handle<D> face;
+
+ private:
typedef complex_bkd_iter_<D> self_;
- typedef internal::complex_iter_< D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -187,7 +113,7 @@ namespace mln
/// Construction and assignment.
/// \{
complex_bkd_iter_();
- // FIXME: See above (internal::complex_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
complex_bkd_iter_(complex<D>& c);
complex_bkd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -213,113 +139,6 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
- /*--------------------------------.
- | internal::complex_iter_<D, E>. |
- `--------------------------------*/
-
- namespace internal
- {
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::complex_iter_()
- {
- // Invalidate face_.
- invalidate();
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::complex_iter_(complex<D>& c)
- {
- face_.set_cplx(c);
- // Invalidate face_.
- invalidate();
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::complex_iter_(const complex_iter_<D, E>& rhs)
- : face_(rhs.face_)
- {
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>&
- complex_iter_<D, E>::operator=(const complex_iter_<D, E>& rhs)
- {
- if (&rhs == this)
- return *this;
- face_ = rhs.face_;
- return *this;
- }
-
- template <unsigned D, typename E>
- inline
- bool
- complex_iter_<D, E>::is_valid() const
- {
- return face_.is_valid();
- }
-
- template <unsigned D, typename E>
- inline
- void
- complex_iter_<D, E>::invalidate()
- {
- face_.set_n(invalid_unsigned_());
- face_.set_face_id(invalid_unsigned_());
- }
-
- template <unsigned D, typename E>
- inline
- const any_face_handle<D>&
- complex_iter_<D, E>::to_face() const
- {
- return face_;
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::operator any_face_handle<D>() const
- {
- mln_precondition(is_valid());
- return face_;
- }
-
- template <unsigned D, typename E>
- unsigned
- complex_iter_<D, E>::invalid_unsigned_() const
- {
- return std::numeric_limits<unsigned>::max();
- }
-
- template <unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_iter_<D, E>& p)
- {
- /* FIXME: We should use p.to_face() here, but as it lacks the
- precondition the conversion operator has, so we use the latter.
-
- We should
- - rename `to_face' as `to_face_';
- - write a new `to_face' routine checking the validity of the
- iterator;
- - have the conversion operator to face use this new `to_face'
- routine;
- - adjust former clients of `to_face'
-
- This is a general remark that applies to all iterators of
- Milena. */
- any_face_handle<D> f = p;
- return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')';
- }
-
- } // end of mln::internal
-
-
/*-----------------------.
| complex_fwd_iter_<D>. |
`-----------------------*/
@@ -334,6 +153,7 @@ namespace mln
template <unsigned D>
inline
complex_fwd_iter_<D>::complex_fwd_iter_(complex<D>& c)
+ : super_(c)
{
set_cplx(c);
mln_postcondition(!is_valid());
@@ -413,8 +233,6 @@ namespace mln
| complex_bkd_iter_<D>. |
`-----------------------*/
- // FIXME: Resume here.
-
template <unsigned D>
inline
complex_bkd_iter_<D>::complex_bkd_iter_()
@@ -425,6 +243,7 @@ namespace mln
template <unsigned D>
inline
complex_bkd_iter_<D>::complex_bkd_iter_(complex<D>& c)
+ : super_(c)
{
set_cplx(c);
mln_postcondition(!is_valid());
diff --git a/milena/mln/core/face.hh b/milena/mln/core/face.hh
index 4e8e958..9fd685a 100644
--- a/milena/mln/core/face.hh
+++ b/milena/mln/core/face.hh
@@ -143,6 +143,9 @@ namespace mln
template <unsigned N, unsigned D>
struct face_handle
{
+ // The type of the complex this handle points to.
+ typedef complex<D> complex_type;
+
/// Build a non-initialized face handle.
face_handle();
/// Build a face handle from \a complex and \a face_id.
@@ -156,6 +159,8 @@ namespace mln
/// Is this handle valid?
bool is_valid() const;
+ /// Invalidate this handle.
+ void invalidate();
/// Accessors.
/// \{
@@ -167,6 +172,9 @@ namespace mln
/// Set the complex the face belongs to.
void set_cplx(complex<D>& cplx);
+ /// Return the dimension of the face.
+ // FIXME: Rename as `dim'?
+ unsigned n() const;
/// Set the id of the face.
void set_face_id(unsigned face_id);
@@ -259,6 +267,9 @@ namespace mln
template <unsigned D>
struct any_face_handle
{
+ // The type of the complex this handle points to.
+ typedef complex<D> complex_type;
+
/// Build a non-initialized face handle.
any_face_handle();
/// Build a face handle from \a complex and \a face_id.
@@ -276,6 +287,8 @@ namespace mln
/// Is this handle valid?
bool is_valid() const;
+ /// Invalidate this handle.
+ void invalidate();
/// Accessors.
/// \{
@@ -411,6 +424,13 @@ namespace mln
}
template <unsigned N, unsigned D>
+ void
+ face_handle<N, D>::invalidate()
+ {
+ set_face_id(std::numeric_limits<unsigned>::max());
+ }
+
+ template <unsigned N, unsigned D>
complex<D>&
face_handle<N, D>::cplx() const
{
@@ -420,6 +440,13 @@ namespace mln
template <unsigned N, unsigned D>
unsigned
+ face_handle<N, D>::n() const
+ {
+ return N;
+ }
+
+ template <unsigned N, unsigned D>
+ unsigned
face_handle<N, D>::face_id() const
{
return face_id_;
@@ -574,6 +601,14 @@ namespace mln
}
template <unsigned D>
+ void
+ any_face_handle<D>::invalidate()
+ {
+ set_n(std::numeric_limits<unsigned>::max());
+ set_face_id(std::numeric_limits<unsigned>::max());
+ }
+
+ template <unsigned D>
complex<D>&
any_face_handle<D>::cplx() const
{
diff --git a/milena/mln/core/faces_iter.hh b/milena/mln/core/faces_iter.hh
index 25dd2c2..e11073d 100644
--- a/milena/mln/core/faces_iter.hh
+++ b/milena/mln/core/faces_iter.hh
@@ -32,99 +32,11 @@
/// \brief Definition of forward and backward iterators on the n-faces
/// of a complex.
-# include <limits>
-
-# include <mln/core/concept/iterator.hh>
-# include <mln/core/complex.hh>
+# include <mln/core/internal/complex_iter_base.hh>
namespace mln
{
- // Fwd decls.
- template <unsigned D> class complex;
-
- /*---------------------------------.
- | internal::faces_iter_<N, D, E>. |
- `---------------------------------*/
-
- // FIXME: Maybe we should have a `face' parameter instead of N & D.
- // This way, we could merge this class and
- // internal::complex_iter_x<D, E>.
-
- namespace internal
- {
- /// \brief Factoring classe for iterators on all the \p N-faces of
- /// a mln::complex<D>.
- ///
- /// \arg \p N The dimension of the face associated to this iterator.
- /// \arg \p D The dimension of the complex this iterator belongs to.
- /// \arg \p E The type exact type of the iterator.
- template <unsigned N, unsigned D, typename E>
- class faces_iter_ : public Iterator<E>
- {
- typedef faces_iter_<N, D, E> self_;
-
- public:
- typedef face_handle<N, D> face;
-
- /// Construction and assignment.
- /// \{
- /* FIXME: Keep this non-const? See a (big) comment about this in
- milena/tests/complex_image.cc. */
- faces_iter_(complex<D>& c);
- faces_iter_(const self_& rhs);
- self_& operator= (const self_& rhs);
- /// \}
-
- /// Manipulation.
- /// \{
- /// Test if the iterator is valid.
- bool is_valid() const;
- /// Invalidate the iterator.
- void invalidate();
- /// \}
-
- /// Conversion and accessors.
- /// \{
- /// Reference to the corresponding face handle.
- const face& to_face () const;
- /// Convert the iterator into an face handle.
- operator face() const;
- /// \}
-
- protected:
- /// The face handle this iterator is pointing to.
- face face_;
-
- private:
- /// \brief An invalid value for both the dimension and the id of
- /// the face.
- ///
- /// Use a function instead of a static constant, since `static'
- /// variables needs to be compiled once, which requires a compiled
- /// library to avoid duplicate symbols, which is something that
- /// was not really planned in Milena. A function tagged `inlined'
- /// can appear multiple times in a program, and solves this
- /// problem. We rely on the compiler to inline this call.
- ///
- /// Of course, we could have used UINT_MAX, but it is not very
- /// C++.
- unsigned invalid_unsigned_() const;
- };
-
-
- /* FIXME: This hand-made delegation is painful. We should rely on
- the general mechanism provided by Point_Site. But then again, we
- need to refine/adjust the interface of Point_Site w.r.t. the
- mandatory conversions to points. */
- template <unsigned N, unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p);
-
- } // end of mln::internal
-
-
/*------------------------.
| faces_fwd_iter_<N, D>. |
`------------------------*/
@@ -135,10 +47,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned N, unsigned D>
class faces_fwd_iter_
- : public internal::faces_iter_< N, D, faces_fwd_iter_<N, D> >
+ : public internal::complex_iter_base_< face_handle<N, D>,
+ faces_fwd_iter_<N, D> >
{
+ public:
+ typedef face_handle<N, D> face;
+
+ private:
typedef faces_fwd_iter_<N, D> self_;
- typedef internal::faces_iter_< N, D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -147,7 +64,7 @@ namespace mln
public:
/// Construction and assignment.
/// \{
- // FIXME: See above (internal::faces_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
faces_fwd_iter_(complex<D>& c);
faces_fwd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -176,10 +93,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned N, unsigned D>
class faces_bkd_iter_
- : public internal::faces_iter_< N, D, faces_bkd_iter_<N, D> >
+ : public internal::complex_iter_base_< face_handle<N, D>,
+ faces_bkd_iter_<N, D> >
{
+ public:
+ typedef face_handle<N, D> face;
+
+ private:
typedef faces_bkd_iter_<N, D> self_;
- typedef internal::faces_iter_< N, D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -188,7 +110,7 @@ namespace mln
public:
/// Construction and assignment.
/// \{
- // FIXME: See above (internal::faces_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
faces_bkd_iter_(complex<D>& c);
faces_bkd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -210,109 +132,6 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
- /*---------------------------------.
- | internal::faces_iter_<N, D, E>. |
- `---------------------------------*/
-
- namespace internal
- {
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>::faces_iter_(complex<D>& c)
- {
- // Ensure N is compatible with D.
- metal::bool_< N <= D >::check();
-
- face_.set_cplx(c);
- // Invalidate face_.
- invalidate();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>::faces_iter_(const faces_iter_<N, D, E>& rhs)
- : face_(rhs.face_)
- {
- // Ensure N is compatible with D.
- metal::bool_< N <= D >::check();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>&
- faces_iter_<N, D, E>::operator=(const faces_iter_<N, D, E>& rhs)
- {
- if (&rhs == this)
- return *this;
- face_ = rhs.face_;
- return *this;
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- bool
- faces_iter_<N, D, E>::is_valid() const
- {
- return face_.is_valid();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- void
- faces_iter_<N, D, E>::invalidate()
- {
- face_.set_face_id(invalid_unsigned_());
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- const face_handle<N, D>&
- faces_iter_<N, D, E>::to_face() const
- {
- return face_;
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>::operator face_handle<N, D>() const
- {
- mln_precondition(is_valid());
- return face_;
- }
-
- template <unsigned N, unsigned D, typename E>
- unsigned
- faces_iter_<N, D, E>::invalid_unsigned_() const
- {
- return std::numeric_limits<unsigned>::max();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p)
- {
- /* FIXME: We should use p.to_face() here, but as it lacks the
- precondition the conversion operator has, so we use the latter.
-
- We should
- - rename `to_face' as `to_face_';
- - write a new `to_face' routine checking the validity of the
- iterator;
- - have the conversion operator to face use this new `to_face'
- routine;
- - adjust former clients of `to_face'
-
- This is a general remark that applies to all iterators of
- Milena. */
- typename faces_iter_<N, D, E>::face f = p;
- return ostr << "(dim = " << N << ", id = " << f.face_id() << ')';
- }
-
- } // end of mln::internal
-
-
/*------------------------.
| faces_fwd_iter_<N, D>. |
`------------------------*/
diff --git a/milena/mln/core/internal/complex_iter_base.hh b/milena/mln/core/internal/complex_iter_base.hh
new file mode 100644
index 0000000..df9b39a
--- /dev/null
+++ b/milena/mln/core/internal/complex_iter_base.hh
@@ -0,0 +1,214 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH
+# define MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH
+
+/// \file mln/core/complex_iter_base.hh
+/// \brief Definition of an implementation (factoring) class for
+/// iterators on complexes.
+
+# include <limits>
+
+# include <mln/metal/equal.hh>
+
+# include <mln/core/concept/iterator.hh>
+# include <mln/core/complex.hh>
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <unsigned D> class complex;
+
+ namespace internal
+ {
+ /// \brief Factoring classe for iterators on complexes.
+ ///
+ /// \arg \p F The type of the face handle.
+ /// \arg \p E The type exact type of the iterator.
+ template <typename F, typename E>
+ class complex_iter_base_ : public Iterator<E>
+ {
+ typedef complex_iter_base_<F, E> self_;
+
+ public:
+ typedef F face;
+ typedef typename F::complex_type complex_type;
+
+ /// Construction and assignment.
+ /// \{
+ /* FIXME: Keep this non-const? See a (big) comment about this in
+ milena/tests/complex_image.cc. */
+ complex_iter_base_();
+ complex_iter_base_(complex_type& c);
+ complex_iter_base_(const self_& rhs);
+ self_& operator= (const self_& rhs);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+ /// \}
+
+ /// Conversion and accessors.
+ /// \{
+ /// Reference to the corresponding face handle.
+ const face& to_face () const;
+ /// Convert the iterator into an face handle.
+ operator face() const;
+ /// \}
+
+ protected:
+ /// The face handle this iterator is pointing to.
+ face face_;
+ };
+
+
+ /* FIXME: This hand-made delegation is painful. We should rely on
+ the general mechanism provided by Point_Site. But then again, we
+ need to refine/adjust the interface of Point_Site w.r.t. the
+ mandatory conversions to points. */
+ template <typename F, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const complex_iter_base_<F, E>& p);
+
+ } // end of mln::internal
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::complex_iter_base_()
+ {
+ // Ensure F and E are compatible.
+ mlc_equal(F, typename E::face)::check();
+
+ invalidate();
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::complex_iter_base_(complex_type& c)
+ {
+ // Ensure F and E are compatible.
+ mlc_equal(F, typename E::face)::check();
+
+ face_.set_cplx(c);
+ // Invalidate face_.
+ invalidate();
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::complex_iter_base_(const complex_iter_base_<F, E>& rhs)
+ : face_(rhs.face_)
+ {
+ // Ensure F and E are compatible.
+ mlc_equal(F, typename E::face)::check();
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>&
+ complex_iter_base_<F, E>::operator=(const complex_iter_base_<F, E>& rhs)
+ {
+ if (&rhs == this)
+ return *this;
+ face_ = rhs.face_;
+ return *this;
+ }
+
+ template <typename F, typename E>
+ inline
+ bool
+ complex_iter_base_<F, E>::is_valid() const
+ {
+ return face_.is_valid();
+ }
+
+ template <typename F, typename E>
+ inline
+ void
+ complex_iter_base_<F, E>::invalidate()
+ {
+ face_.invalidate();
+ }
+
+ template <typename F, typename E>
+ inline
+ const F&
+ complex_iter_base_<F, E>::to_face() const
+ {
+ return face_;
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::operator F() const
+ {
+ mln_precondition(is_valid());
+ return face_;
+ }
+
+
+ template <typename F, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const complex_iter_base_<F, E>& p)
+ {
+ /* FIXME: We should use p.to_face() here, but as it lacks the
+ precondition the conversion operator has, so we use the latter.
+
+ We should
+ - rename `to_face' as `to_face_';
+ - write a new `to_face' routine checking the validity of the
+ iterator;
+ - have the conversion operator to face use this new `to_face'
+ routine;
+ - adjust former clients of `to_face'
+
+ This is a general remark that applies to all iterators of
+ Milena. */
+ F f = p;
+ return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')';
+ }
+
+ } // end of mln::internal
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of mln
+
+#endif // ! MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH
--
1.6.0.1
* mln/core/faces_iter.hh: New.
* mln/core/complex.hh: Add forward declarations for
faces_fwd_iter_ and faces_bkd_iter_.
(mln::complex<D>::fwd_fiter<N>, mln::complex<D>::bkd_fiter<N>):
New inner classes.
* mln/core/face.hh
(mln::face_handle<N, D>::set_cplx)
(mln::face_handle<N, D>::set_face_id):
New mutators.
* mln/core/macros.hh (mln_fiter, mln_fiter_)
(mln_fwd_fiter, mln_fwd_fiter_, mln_bkd_fiter, mln_bkd_fiter_):
New macros.
* tests/core/complex.cc (main): Exercise iterators on n-faces.
---
milena/ChangeLog | 18 ++
milena/mln/core/complex.hh | 19 ++-
milena/mln/core/face.hh | 19 ++
milena/mln/core/faces_iter.hh | 448 +++++++++++++++++++++++++++++++++++++++++
milena/mln/core/macros.hh | 18 ++
milena/tests/core/complex.cc | 43 +++-
6 files changed, 549 insertions(+), 16 deletions(-)
create mode 100644 milena/mln/core/faces_iter.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index e766670..f164de6 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,23 @@
2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+ Add iterators on the n-faces of a complex.
+
+ * mln/core/faces_iter.hh: New.
+ * mln/core/complex.hh: Add forward declarations for
+ faces_fwd_iter_ and faces_bkd_iter_.
+ (mln::complex<D>::fwd_fiter<N>, mln::complex<D>::bkd_fiter<N>):
+ New inner classes.
+ * mln/core/face.hh
+ (mln::face_handle<N, D>::set_cplx)
+ (mln::face_handle<N, D>::set_face_id):
+ New mutators.
+ * mln/core/macros.hh (mln_fiter, mln_fiter_)
+ (mln_fwd_fiter, mln_fwd_fiter_, mln_bkd_fiter, mln_bkd_fiter_):
+ New macros.
+ * tests/core/complex.cc (main): Exercise iterators on n-faces.
+
+2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+
Factor iterators on complexes.
* mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
diff --git a/milena/mln/core/complex.hh b/milena/mln/core/complex.hh
index c0c1b80..3b4571b 100644
--- a/milena/mln/core/complex.hh
+++ b/milena/mln/core/complex.hh
@@ -31,10 +31,8 @@
/// \file mln/core/complex.hh
/// \brief Structures for general complexes.
///
-/// A complexes defines a topological space which can be used as a
+/// A complex defines a topological space which can be used as a
/// support for an image (i.e., as site sets).
-///
-/// FIXME: More.
# include <cstddef>
@@ -44,8 +42,8 @@
# include <mln/metal/bool.hh>
# include <mln/core/face.hh>
-
# include <mln/core/complex_iter.hh>
+# include <mln/core/faces_iter.hh>
namespace mln
@@ -59,6 +57,8 @@ namespace mln
}
template <unsigned D> class complex_fwd_iter_;
template <unsigned D> class complex_bkd_iter_;
+ template <unsigned N, unsigned D> class faces_fwd_iter_;
+ template <unsigned N, unsigned D> class faces_bkd_iter_;
/*----------.
@@ -70,11 +70,18 @@ namespace mln
class complex : private internal::faces_set_mixin<D, D>
{
public:
- /// Forward mln::Iterator associated type.
+ /// Forward mln::Iterator type iterating on all faces.
typedef complex_fwd_iter_<D> fwd_citer;
- /// Backward mln::Iterator associated type.
+ /// Backward mln::Iterator type iterating on all faces.
typedef complex_bkd_iter_<D> bkd_citer;
+ /// Forward mln::Iterator type iterating on \p N-faces.
+ template <unsigned N>
+ struct fwd_fiter { typedef faces_fwd_iter_<N, D> ret; };
+ /// Backward mln::Iterator type iterating on \p N-faces.
+ template <unsigned N>
+ struct bkd_fiter { typedef faces_bkd_iter_<N, D> ret; };
+
/// Complex construction.
/// \{
/// \brief Add a 0-face to the complex.
diff --git a/milena/mln/core/face.hh b/milena/mln/core/face.hh
index 7de0e8d..4e8e958 100644
--- a/milena/mln/core/face.hh
+++ b/milena/mln/core/face.hh
@@ -165,6 +165,11 @@ namespace mln
// FIXME: Rename as `id'?
unsigned face_id() const;
+ /// Set the complex the face belongs to.
+ void set_cplx(complex<D>& cplx);
+ /// Set the id of the face.
+ void set_face_id(unsigned face_id);
+
/// Return the mln::face pointed by this handle.
face<N, D>& to_face() const;
/// \}
@@ -421,6 +426,20 @@ namespace mln
}
template <unsigned N, unsigned D>
+ void
+ face_handle<N, D>::set_cplx(complex<D>& cplx)
+ {
+ cplx_ = &cplx;
+ }
+
+ template <unsigned N, unsigned D>
+ void
+ face_handle<N, D>::set_face_id(unsigned face_id)
+ {
+ face_id_ = face_id;
+ }
+
+ template <unsigned N, unsigned D>
face<N, D>&
face_handle<N, D>::to_face() const
{
diff --git a/milena/mln/core/faces_iter.hh b/milena/mln/core/faces_iter.hh
new file mode 100644
index 0000000..25dd2c2
--- /dev/null
+++ b/milena/mln/core/faces_iter.hh
@@ -0,0 +1,448 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_FACES_ITER_HH
+# define MLN_CORE_FACES_ITER_HH
+
+/// \file mln/core/faces_iter.hh
+/// \brief Definition of forward and backward iterators on the n-faces
+/// of a complex.
+
+# include <limits>
+
+# include <mln/core/concept/iterator.hh>
+# include <mln/core/complex.hh>
+
+namespace mln
+{
+
+ // Fwd decls.
+ template <unsigned D> class complex;
+
+ /*---------------------------------.
+ | internal::faces_iter_<N, D, E>. |
+ `---------------------------------*/
+
+ // FIXME: Maybe we should have a `face' parameter instead of N & D.
+ // This way, we could merge this class and
+ // internal::complex_iter_x<D, E>.
+
+ namespace internal
+ {
+ /// \brief Factoring classe for iterators on all the \p N-faces of
+ /// a mln::complex<D>.
+ ///
+ /// \arg \p N The dimension of the face associated to this iterator.
+ /// \arg \p D The dimension of the complex this iterator belongs to.
+ /// \arg \p E The type exact type of the iterator.
+ template <unsigned N, unsigned D, typename E>
+ class faces_iter_ : public Iterator<E>
+ {
+ typedef faces_iter_<N, D, E> self_;
+
+ public:
+ typedef face_handle<N, D> face;
+
+ /// Construction and assignment.
+ /// \{
+ /* FIXME: Keep this non-const? See a (big) comment about this in
+ milena/tests/complex_image.cc. */
+ faces_iter_(complex<D>& c);
+ faces_iter_(const self_& rhs);
+ self_& operator= (const self_& rhs);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+ /// \}
+
+ /// Conversion and accessors.
+ /// \{
+ /// Reference to the corresponding face handle.
+ const face& to_face () const;
+ /// Convert the iterator into an face handle.
+ operator face() const;
+ /// \}
+
+ protected:
+ /// The face handle this iterator is pointing to.
+ face face_;
+
+ private:
+ /// \brief An invalid value for both the dimension and the id of
+ /// the face.
+ ///
+ /// Use a function instead of a static constant, since `static'
+ /// variables needs to be compiled once, which requires a compiled
+ /// library to avoid duplicate symbols, which is something that
+ /// was not really planned in Milena. A function tagged `inlined'
+ /// can appear multiple times in a program, and solves this
+ /// problem. We rely on the compiler to inline this call.
+ ///
+ /// Of course, we could have used UINT_MAX, but it is not very
+ /// C++.
+ unsigned invalid_unsigned_() const;
+ };
+
+
+ /* FIXME: This hand-made delegation is painful. We should rely on
+ the general mechanism provided by Point_Site. But then again, we
+ need to refine/adjust the interface of Point_Site w.r.t. the
+ mandatory conversions to points. */
+ template <unsigned N, unsigned D, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p);
+
+ } // end of mln::internal
+
+
+ /*------------------------.
+ | faces_fwd_iter_<N, D>. |
+ `------------------------*/
+
+ /// \brief Forward iterator on all the faces of a mln::complex<D>.
+ ///
+ /// \arg \p N The dimension of the face associated to this iterator.
+ /// \arg \p D The dimension of the complex this iterator belongs to.
+ template <unsigned N, unsigned D>
+ class faces_fwd_iter_
+ : public internal::faces_iter_< N, D, faces_fwd_iter_<N, D> >
+ {
+ typedef faces_fwd_iter_<N, D> self_;
+ typedef internal::faces_iter_< N, D, self_ > super_;
+
+ public:
+ using super_::is_valid;
+ using super_::invalidate;
+
+ public:
+ /// Construction and assignment.
+ /// \{
+ // FIXME: See above (internal::faces_iter_'s default ctor).
+ faces_fwd_iter_(complex<D>& c);
+ faces_fwd_iter_(const self_& rhs);
+ self_& operator= (const self_& rhs);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ void start();
+ /// Go to the next point.
+ void next_();
+ /// \}
+
+ private:
+ using super_::face_;
+ };
+
+
+ /*------------------------.
+ | faces_bkd_iter_<N, D>. |
+ `------------------------*/
+
+ /// \brief Backward iterator on all the faces of a mln::complex<D>.
+ ///
+ /// \arg \p N The dimension of the face associated to this iterator.
+ /// \arg \p D The dimension of the complex this iterator belongs to.
+ template <unsigned N, unsigned D>
+ class faces_bkd_iter_
+ : public internal::faces_iter_< N, D, faces_bkd_iter_<N, D> >
+ {
+ typedef faces_bkd_iter_<N, D> self_;
+ typedef internal::faces_iter_< N, D, self_ > super_;
+
+ public:
+ using super_::is_valid;
+ using super_::invalidate;
+
+ public:
+ /// Construction and assignment.
+ /// \{
+ // FIXME: See above (internal::faces_iter_'s default ctor).
+ faces_bkd_iter_(complex<D>& c);
+ faces_bkd_iter_(const self_& rhs);
+ self_& operator= (const self_& rhs);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Start an iteration.
+ void start();
+ /// Go to the next point.
+ void next_();
+ /// \}
+
+ private:
+ using super_::face_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ /*---------------------------------.
+ | internal::faces_iter_<N, D, E>. |
+ `---------------------------------*/
+
+ namespace internal
+ {
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ faces_iter_<N, D, E>::faces_iter_(complex<D>& c)
+ {
+ // Ensure N is compatible with D.
+ metal::bool_< N <= D >::check();
+
+ face_.set_cplx(c);
+ // Invalidate face_.
+ invalidate();
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ faces_iter_<N, D, E>::faces_iter_(const faces_iter_<N, D, E>& rhs)
+ : face_(rhs.face_)
+ {
+ // Ensure N is compatible with D.
+ metal::bool_< N <= D >::check();
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ faces_iter_<N, D, E>&
+ faces_iter_<N, D, E>::operator=(const faces_iter_<N, D, E>& rhs)
+ {
+ if (&rhs == this)
+ return *this;
+ face_ = rhs.face_;
+ return *this;
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ bool
+ faces_iter_<N, D, E>::is_valid() const
+ {
+ return face_.is_valid();
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ void
+ faces_iter_<N, D, E>::invalidate()
+ {
+ face_.set_face_id(invalid_unsigned_());
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ const face_handle<N, D>&
+ faces_iter_<N, D, E>::to_face() const
+ {
+ return face_;
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ faces_iter_<N, D, E>::operator face_handle<N, D>() const
+ {
+ mln_precondition(is_valid());
+ return face_;
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ unsigned
+ faces_iter_<N, D, E>::invalid_unsigned_() const
+ {
+ return std::numeric_limits<unsigned>::max();
+ }
+
+ template <unsigned N, unsigned D, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p)
+ {
+ /* FIXME: We should use p.to_face() here, but as it lacks the
+ precondition the conversion operator has, so we use the latter.
+
+ We should
+ - rename `to_face' as `to_face_';
+ - write a new `to_face' routine checking the validity of the
+ iterator;
+ - have the conversion operator to face use this new `to_face'
+ routine;
+ - adjust former clients of `to_face'
+
+ This is a general remark that applies to all iterators of
+ Milena. */
+ typename faces_iter_<N, D, E>::face f = p;
+ return ostr << "(dim = " << N << ", id = " << f.face_id() << ')';
+ }
+
+ } // end of mln::internal
+
+
+ /*------------------------.
+ | faces_fwd_iter_<N, D>. |
+ `------------------------*/
+
+ template <unsigned N, unsigned D>
+ inline
+ faces_fwd_iter_<N, D>::faces_fwd_iter_(complex<D>& c)
+ : super_(c)
+ {
+ // Ensure N is compatible with D.
+ metal::bool_< N <= D >::check();
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ faces_fwd_iter_<N, D>::faces_fwd_iter_(const faces_fwd_iter_<N, D>& rhs)
+ : super_(rhs)
+ {
+ // Ensure N is compatible with D.
+ metal::bool_< N <= D >::check();
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ faces_fwd_iter_<N, D>&
+ faces_fwd_iter_<N, D>::operator=(const faces_fwd_iter_<N, D>& rhs)
+ {
+ if (&rhs == this)
+ return *this;
+ super_::operator=(rhs);
+ return *this;
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ void
+ faces_fwd_iter_<N, D>::start()
+ {
+ face_.set_face_id(0u);
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ void
+ faces_fwd_iter_<N, D>::next_()
+ {
+ if (is_valid())
+ {
+ unsigned face_id = face_.face_id();
+ if (face_id + 1 < face_.cplx().template nfaces<N>())
+ /* FIXME: Provide accessor face_handle::n() returning
+ a mutable reference? This way, we could just write
+
+ ++face_.face_id();
+
+ instead of the following. */
+ face_.set_face_id(face_id + 1);
+ else
+ invalidate();
+ }
+ }
+
+
+ /*------------------------.
+ | faces_bkd_iter_<N, D>. |
+ `------------------------*/
+
+ // FIXME: Resume here.
+
+ template <unsigned N, unsigned D>
+ inline
+ faces_bkd_iter_<N, D>::faces_bkd_iter_(complex<D>& c)
+ : super_(c)
+ {
+ // Ensure N is compatible with D.
+ metal::bool_< N <= D >::check();
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ faces_bkd_iter_<N, D>::faces_bkd_iter_(const faces_bkd_iter_<N, D>& rhs)
+ : super_(rhs)
+ {
+ // Ensure N is compatible with D.
+ metal::bool_< N <= D >::check();
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ faces_bkd_iter_<N, D>&
+ faces_bkd_iter_<N, D>::operator=(const faces_bkd_iter_<N, D>& rhs)
+ {
+ if (&rhs == this)
+ return *this;
+ super_::operator=(rhs);
+ return *this;
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ void
+ faces_bkd_iter_<N, D>::start()
+ {
+ face_.set_face_id(face_.cplx().template nfaces<N>() - 1);
+ }
+
+ template <unsigned N, unsigned D>
+ inline
+ void
+ faces_bkd_iter_<N, D>::next_()
+ {
+ if (is_valid())
+ {
+ unsigned face_id = face_.face_id();
+ if (face_id > 0)
+ /* FIXME: Provide accessor face_handle::n() returning
+ a mutable reference? This way, we could just write
+
+ ++face_.face_id();
+
+ instead of the following. */
+ face_.set_face_id(face_id - 1);
+ else
+ invalidate();
+ }
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of mln
+
+
+#endif // ! MLN_CORE_FACES_ITER_HH
diff --git a/milena/mln/core/macros.hh b/milena/mln/core/macros.hh
index a7376ca..d098814 100644
--- a/milena/mln/core/macros.hh
+++ b/milena/mln/core/macros.hh
@@ -51,6 +51,12 @@
# define mln_bkd_citer_(T) T::bkd_citer
/// \}
+/// Shortcuts to access the (N-faces) bkd_fiter type associated to T.
+/// \{
+# define mln_bkd_fiter(N, T) typename T::template bkd_fiter< N >::ret
+# define mln_bkd_fiter_(N, T) T:: bkd_fiter< N >::ret
+/// \}
+
/// Shortcuts to access the bkd_niter type associated to T.
/// \{
# define mln_bkd_niter(T) typename T::bkd_niter
@@ -123,12 +129,24 @@
// f
+/// Shortcuts to access the (N-faces) fiter type associated to T.
+/// \{
+# define mln_fiter(N, T) typename T::template fwd_fiter< N >::ret
+# define mln_fiter_(N, T) T:: fwd_fiter< N >::ret
+/// \}
+
/// Shortcuts to access the fwd_citer type associated to T.
/// \{
# define mln_fwd_citer(T) typename T::fwd_citer
# define mln_fwd_citer_(T) T::fwd_citer
/// \}
+/// Shortcuts to access the (N-faces) fwd_fiter type associated to T.
+/// \{
+# define mln_fwd_fiter(N, T) typename T::template fwd_fiter< N >::ret
+# define mln_fwd_fiter_(N, T) T:: fwd_fiter< N >::ret
+/// \}
+
/// Shortcuts to access the fwd_niter type associated to T.
/// \{
# define mln_fwd_niter(T) typename T::fwd_niter
diff --git a/milena/tests/core/complex.cc b/milena/tests/core/complex.cc
index 91bae55..49ec3d4 100644
--- a/milena/tests/core/complex.cc
+++ b/milena/tests/core/complex.cc
@@ -32,11 +32,15 @@
#include <mln/core/complex.hh>
+using namespace mln;
+
+
+// Forward declaration.
+template <unsigned N, unsigned D> void test_faces_iter(complex<D>& c);
+
int main()
{
- using namespace mln;
-
/* A 2-d (simplicial) complex and its adjacency graph.
v0 e3 v3
@@ -94,7 +98,8 @@ int main()
<< "Using ``dynamic'' manipulators." << std::endl
<< " number of 0-faces: c.nfaces(0) = " << c.nfaces(0) << std::endl
<< " number of 1-faces: c.nfaces(1) = " << c.nfaces(1) << std::endl
- << " number of 2-faces: c.nfaces(2) = " << c.nfaces(2) << std::endl;
+ << " number of 2-faces: c.nfaces(2) = " << c.nfaces(2) << std::endl
+ << std::endl;
/*-------------------.
| Handles and data. |
@@ -110,24 +115,31 @@ int main()
mln_assertion(&face1 == &face2);
-
/*------------.
| Iteration. |
`------------*/
// FIXME: Possibly split this test (create a test for iterators).
+ // --------------- //
+ // Iterator on C. //
+ // --------------- //
+
// Iterators on a complex (not complex_image), or more precisely on
// (all) the faces of complex C.
mln_fwd_citer_(complex<D>) fwd_f(c);
- for_all(fwd_f)
- std::cout << fwd_f << std::endl;
-
+ mln_bkd_citer_(complex<D>) bkd_f(c);
+ for_all_2(fwd_f, bkd_f)
+ std::cout << fwd_f << ' ' << bkd_f << std::endl;
std::cout << std::endl;
- mln_bkd_citer_(complex<D>) bkd_f(c);
- for_all(bkd_f)
- std::cout << bkd_f << std::endl;
+ // -------------------------- //
+ // Iterator on n-faces of C. //
+ // -------------------------- //
+
+ test_faces_iter<0>(c);
+ test_faces_iter<1>(c);
+ test_faces_iter<2>(c);
/* FIXME: Exercice more iterators (see
milena/tests/core/complex_image.cc) and ticket #162
@@ -135,3 +147,14 @@ int main()
// ...
}
+
+template <unsigned N, unsigned D>
+void
+test_faces_iter(complex<D>& c)
+{
+ mln_fwd_fiter(N, complex<D>) fwd_nf(c);
+ mln_bkd_fiter(N, complex<D>) bkd_nf(c);
+ for_all_2(fwd_nf, bkd_nf)
+ std::cout << fwd_nf << ' ' << bkd_nf << std::endl;
+ std::cout << std::endl;
+}
--
1.6.0.1
* mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
New class.
Use it to factor...
(mln::complex_fwd_iter_<D>, mln::complex_bkd_iter_<D>):
...these.
(operator<<(std::ostream&, const complex_iter_<D, E>&)):
New.
(operator<<(std::ostream&, const complex_fwd_iter_<D>&))
(operator<<(std::ostream&, const complex_bkd_iter_<D>&)):
Remove.
* tests/core/complex.cc: Use clearer names for iterators.
---
milena/ChangeLog | 16 ++
milena/mln/core/complex_iter.hh | 410 ++++++++++++++++++++-------------------
milena/tests/core/complex.cc | 17 +-
3 files changed, 238 insertions(+), 205 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cd60428..e766670 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,19 @@
+2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Factor iterators on complexes.
+
+ * mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
+ New class.
+ Use it to factor...
+ (mln::complex_fwd_iter_<D>, mln::complex_bkd_iter_<D>):
+ ...these.
+ (operator<<(std::ostream&, const complex_iter_<D, E>&)):
+ New.
+ (operator<<(std::ostream&, const complex_fwd_iter_<D>&))
+ (operator<<(std::ostream&, const complex_bkd_iter_<D>&)):
+ Remove.
+ * tests/core/complex.cc: Use clearer names for iterators.
+
2008-09-11 Roland Levillain <roland(a)lrde.epita.fr>
Factor iterators on p_complexes with iterator on complexes.
diff --git a/milena/mln/core/complex_iter.hh b/milena/mln/core/complex_iter.hh
index 7588a32..4aa9b99 100644
--- a/milena/mln/core/complex_iter.hh
+++ b/milena/mln/core/complex_iter.hh
@@ -31,40 +31,118 @@
/// \file mln/core/complex_iter.hh
/// \brief Definition of forward and backward iterators on complexes.
-
# include <limits>
# include <mln/core/concept/iterator.hh>
# include <mln/core/complex.hh>
-
-// Factor complex_fwd_iter_<D> and complex_bkd_iter_<D>?
-
namespace mln
{
// Fwd decls.
template <unsigned D> class complex;
+ /*--------------------------------.
+ | internal::complex_iter_<D, E>. |
+ `--------------------------------*/
+
+ namespace internal
+ {
+ /// \brief Factoring classe for iterators on all the faces of
+ /// a mln::complex<D>.
+ ///
+ /// \arg \p D The dimension of the complex this iterator belongs to.
+ /// \arg \p E The type exact type of the iterator.
+ template <unsigned D, typename E>
+ class complex_iter_ : public Iterator<E>
+ {
+ typedef complex_iter_<D, E> self_;
+
+ public:
+ typedef any_face_handle<D> face;
+
+ /// Construction and assignment.
+ /// \{
+ complex_iter_();
+ /* FIXME: Keep this non-const? See a (big) comment about this in
+ milena/tests/complex_image.cc. */
+ complex_iter_(complex<D>& c);
+ complex_iter_(const self_& rhs);
+ self_& operator= (const self_& rhs);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+ /// \}
+
+ /// Conversion and accessors.
+ /// \{
+ /// Reference to the corresponding any-face handle.
+ const face& to_face () const;
+ /// Convert the iterator into an any-face handle.
+ operator face() const;
+ /// \}
+
+ protected:
+ /// The face handle this iterator is pointing to.
+ face face_;
+
+ private:
+ /// \brief An invalid value for both the dimension and the id of
+ /// the face.
+ ///
+ /// Use a function instead of a static constant, since `static'
+ /// variables needs to be compiled once, which requires a compiled
+ /// library to avoid duplicate symbols, which is something that
+ /// was not really planned in Milena. A function tagged `inlined'
+ /// can appear multiple times in a program, and solves this
+ /// problem. We rely on the compiler to inline this call.
+ ///
+ /// Of course, we could have used UINT_MAX, but it is not very
+ /// C++.
+ unsigned invalid_unsigned_() const;
+ };
+
+
+ /* FIXME: This hand-made delegation is painful. We should rely on
+ the general mechanism provided by Point_Site. But then again, we
+ need to refine/adjust the interface of Point_Site w.r.t. the
+ mandatory conversions to points. */
+ template <unsigned D, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const complex_iter_<D, E>& p);
+
+ } // end of mln::internal
+
/*-----------------------.
| complex_fwd_iter_<D>. |
`-----------------------*/
- /// \brief Forward iterator on all the faces of mln::complex<D>.
+ /// \brief Forward iterator on all the faces of a mln::complex<D>.
+ ///
+ /// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned D>
- class complex_fwd_iter_ : public Iterator< complex_fwd_iter_<D> >
+ class complex_fwd_iter_
+ : public internal::complex_iter_< D, complex_fwd_iter_<D> >
{
typedef complex_fwd_iter_<D> self_;
+ typedef internal::complex_iter_< D, self_ > super_;
public:
- typedef any_face_handle<D> face;
+ using super_::is_valid;
+ using super_::invalidate;
+ public:
/// Construction and assignment.
/// \{
complex_fwd_iter_();
- /* FIXME: Keep this non-const? See a (big) comment about this in
- milena/tests/complex_image.cc. */
+ // FIXME: See above (internal::complex_iter_'s default ctor).
complex_fwd_iter_(complex<D>& c);
complex_fwd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -77,72 +155,39 @@ namespace mln
void set_cplx(complex<D>& c);
/// Test if the iterator is valid.
- bool is_valid() const;
- /// Invalidate the iterator.
- void invalidate();
- /// Start an iteration.
void start();
-
/// Go to the next point.
void next_();
/// \}
- /// Conversion and accessors.
- /// \{
- /// Reference to the corresponding any-face handle.
- const face& to_face () const;
- /// Convert the iterator into an any-face handle.
- operator face() const;
- /// \}
-
private:
- /// The face handle this iterator is pointing to.
- face face_;
-
- /// \brief An invalid value for both the dimension and the id of
- /// the face.
- ///
- /// Use a function instead of a static constant, since `static'
- /// variables needs to be compiled once, which requires a compiled
- /// library to avoid duplicate symbols, which is something that
- /// was not really planned in Milena. A function tagged `inlined'
- /// can appear multiple times in a program, and solves this
- /// problem. We rely on the compiler to inline this call.
- ///
- /// Of course, we could have used UINT_MAX, but it is not very
- /// C++.
- unsigned invalid_unsigned_() const;
+ using super_::face_;
};
- /* FIXME: This hand-made delegation is painful. We should rely on
- the general mechanism provided by Point_Site. But then again, we
- need to refine/adjust the interface of Point_Site w.r.t. the
- mandatory conversions to points. */
- template <unsigned D>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_fwd_iter_<D>& p);
-
-
/*-----------------------.
| complex_bkd_iter_<D>. |
`-----------------------*/
- /// \brief Backward iterator on all the faces of mln::complex<D>.
+ /// \brief Backward iterator on all the faces of a mln::complex<D>.
+ ///
+ /// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned D>
- class complex_bkd_iter_ : public Iterator< complex_bkd_iter_<D> >
+ class complex_bkd_iter_
+ : public internal::complex_iter_< D, complex_bkd_iter_<D> >
{
typedef complex_bkd_iter_<D> self_;
+ typedef internal::complex_iter_< D, self_ > super_;
public:
- typedef any_face_handle<D> face;
+ using super_::is_valid;
+ using super_::invalidate;
+ public:
/// Construction and assignment.
/// \{
complex_bkd_iter_();
- /* FIXME: Keep this non-const? See a (big) comment about this in
- milena/tests/complex_image.cc. */
+ // FIXME: See above (internal::complex_iter_'s default ctor).
complex_bkd_iter_(complex<D>& c);
complex_bkd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -154,57 +199,126 @@ namespace mln
// FIXME: Same comment as the ctor above.
void set_cplx(complex<D>& c);
- /// Test if the iterator is valid.
- bool is_valid() const;
- /// Invalidate the iterator.
- void invalidate();
/// Start an iteration.
void start();
-
/// Go to the next point.
void next_();
/// \}
- /// Conversion and accessors.
- /// \{
- /// Reference to the corresponding any-face handle.
- const face& to_face () const;
- /// Convert the iterator into an any-face handle.
- operator face() const;
- /// \}
-
private:
- /// The face handle this iterator is pointing to.
- face face_;
-
- /// \brief An invalid value for both the dimension and the id of
- /// the face.
- ///
- /// Use a function instead of a static constant, since `static'
- /// variables needs to be compiled once, which requires a compiled
- /// library to avoid duplicate symbols, which is something that
- /// was not really planned in Milena. A function tagged `inlined'
- /// can appear multiple times in a program, and solves this
- /// problem. We rely on the compiler to inline this call.
- ///
- /// Of course, we could have used UINT_MAX, but it is not very
- /// C++.
- unsigned invalid_unsigned_() const;
+ using super_::face_;
};
- /* FIXME: This hand-made delegation is painful. We should rely on
- the general mechanism provided by Point_Site. But then again, we
- need to refine/adjust the interface of Point_Site w.r.t. the
- mandatory conversions to points. */
- template <unsigned D>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_bkd_iter_<D>& p);
+# ifndef MLN_INCLUDE_ONLY
+ /*--------------------------------.
+ | internal::complex_iter_<D, E>. |
+ `--------------------------------*/
+
+ namespace internal
+ {
+
+ template <unsigned D, typename E>
+ inline
+ complex_iter_<D, E>::complex_iter_()
+ {
+ // Invalidate face_.
+ invalidate();
+ }
+
+ template <unsigned D, typename E>
+ inline
+ complex_iter_<D, E>::complex_iter_(complex<D>& c)
+ {
+ face_.set_cplx(c);
+ // Invalidate face_.
+ invalidate();
+ }
+
+ template <unsigned D, typename E>
+ inline
+ complex_iter_<D, E>::complex_iter_(const complex_iter_<D, E>& rhs)
+ : face_(rhs.face_)
+ {
+ }
+
+ template <unsigned D, typename E>
+ inline
+ complex_iter_<D, E>&
+ complex_iter_<D, E>::operator=(const complex_iter_<D, E>& rhs)
+ {
+ if (&rhs == this)
+ return *this;
+ face_ = rhs.face_;
+ return *this;
+ }
+
+ template <unsigned D, typename E>
+ inline
+ bool
+ complex_iter_<D, E>::is_valid() const
+ {
+ return face_.is_valid();
+ }
+
+ template <unsigned D, typename E>
+ inline
+ void
+ complex_iter_<D, E>::invalidate()
+ {
+ face_.set_n(invalid_unsigned_());
+ face_.set_face_id(invalid_unsigned_());
+ }
+
+ template <unsigned D, typename E>
+ inline
+ const any_face_handle<D>&
+ complex_iter_<D, E>::to_face() const
+ {
+ return face_;
+ }
+
+ template <unsigned D, typename E>
+ inline
+ complex_iter_<D, E>::operator any_face_handle<D>() const
+ {
+ mln_precondition(is_valid());
+ return face_;
+ }
+
+ template <unsigned D, typename E>
+ unsigned
+ complex_iter_<D, E>::invalid_unsigned_() const
+ {
+ return std::numeric_limits<unsigned>::max();
+ }
+
+ template <unsigned D, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const complex_iter_<D, E>& p)
+ {
+ /* FIXME: We should use p.to_face() here, but as it lacks the
+ precondition the conversion operator has, so we use the latter.
+
+ We should
+ - rename `to_face' as `to_face_';
+ - write a new `to_face' routine checking the validity of the
+ iterator;
+ - have the conversion operator to face use this new `to_face'
+ routine;
+ - adjust former clients of `to_face'
+
+ This is a general remark that applies to all iterators of
+ Milena. */
+ any_face_handle<D> f = p;
+ return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')';
+ }
+
+ } // end of mln::internal
-# ifndef MLN_INCLUDE_ONLY
/*-----------------------.
| complex_fwd_iter_<D>. |
@@ -213,8 +327,8 @@ namespace mln
template <unsigned D>
inline
complex_fwd_iter_<D>::complex_fwd_iter_()
+ : super_()
{
- invalidate();
}
template <unsigned D>
@@ -228,7 +342,7 @@ namespace mln
template <unsigned D>
inline
complex_fwd_iter_<D>::complex_fwd_iter_(const complex_fwd_iter_<D>& rhs)
- : face_(rhs.face_)
+ : super_(rhs)
{
}
@@ -239,7 +353,7 @@ namespace mln
{
if (&rhs == this)
return *this;
- face_ = rhs.face_;
+ super_::operator=(rhs);
return *this;
}
@@ -255,23 +369,6 @@ namespace mln
template <unsigned D>
inline
- bool
- complex_fwd_iter_<D>::is_valid() const
- {
- return face_.is_valid();
- }
-
- template <unsigned D>
- inline
- void
- complex_fwd_iter_<D>::invalidate()
- {
- face_.set_n(invalid_unsigned_());
- face_.set_face_id(invalid_unsigned_());
- }
-
- template <unsigned D>
- inline
void
complex_fwd_iter_<D>::start()
{
@@ -311,49 +408,18 @@ namespace mln
}
}
- template <unsigned D>
- inline
- const any_face_handle<D>&
- complex_fwd_iter_<D>::to_face() const
- {
- return face_;
- }
-
- template <unsigned D>
- inline
- complex_fwd_iter_<D>::operator any_face_handle<D>() const
- {
- mln_precondition(is_valid());
- return face_;
- }
-
- template <unsigned D>
- unsigned
- complex_fwd_iter_<D>::invalid_unsigned_() const
- {
- return std::numeric_limits<unsigned>::max();
- }
-
-
- template <unsigned D>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_fwd_iter_<D>& p)
- {
- return ostr << "(dim = " << p.to_face().n()
- << ", id = " << p.to_face().face_id() << ')';
- }
-
/*-----------------------.
| complex_bkd_iter_<D>. |
`-----------------------*/
+ // FIXME: Resume here.
+
template <unsigned D>
inline
complex_bkd_iter_<D>::complex_bkd_iter_()
+ : super_()
{
- invalidate();
}
template <unsigned D>
@@ -367,7 +433,7 @@ namespace mln
template <unsigned D>
inline
complex_bkd_iter_<D>::complex_bkd_iter_(const complex_bkd_iter_<D>& rhs)
- : face_(rhs.face_)
+ : super_(rhs)
{
}
@@ -378,7 +444,7 @@ namespace mln
{
if (&rhs == this)
return *this;
- face_ = rhs.face_;
+ super_::operator=(rhs);
return *this;
}
@@ -394,23 +460,6 @@ namespace mln
template <unsigned D>
inline
- bool
- complex_bkd_iter_<D>::is_valid() const
- {
- return face_.is_valid();
- }
-
- template <unsigned D>
- inline
- void
- complex_bkd_iter_<D>::invalidate()
- {
- face_.set_n(invalid_unsigned_());
- face_.set_face_id(invalid_unsigned_());
- }
-
- template <unsigned D>
- inline
void
complex_bkd_iter_<D>::start()
{
@@ -450,39 +499,6 @@ namespace mln
}
}
- template <unsigned D>
- inline
- const any_face_handle<D>&
- complex_bkd_iter_<D>::to_face() const
- {
- return face_;
- }
-
- template <unsigned D>
- inline
- complex_bkd_iter_<D>::operator any_face_handle<D>() const
- {
- mln_precondition(is_valid());
- return face_;
- }
-
- template <unsigned D>
- unsigned
- complex_bkd_iter_<D>::invalid_unsigned_() const
- {
- return std::numeric_limits<unsigned>::max();
- }
-
-
- template <unsigned D>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_bkd_iter_<D>& p)
- {
- return ostr << "(dim = " << p.to_face().n()
- << ", id = " << p.to_face().face_id() << ')';
- }
-
# endif // ! MLN_INCLUDE_ONLY
} // end of mln
diff --git a/milena/tests/core/complex.cc b/milena/tests/core/complex.cc
index 1bacd6e..91bae55 100644
--- a/milena/tests/core/complex.cc
+++ b/milena/tests/core/complex.cc
@@ -115,18 +115,19 @@ int main()
| Iteration. |
`------------*/
- // Iterators on a complex (not complex_image), or more precisely on
- // the faces of a complex.
+ // FIXME: Possibly split this test (create a test for iterators).
- mln_fwd_citer_(complex<D>) ff(c);
- for_all(ff)
- std::cout << ff << std::endl;
+ // Iterators on a complex (not complex_image), or more precisely on
+ // (all) the faces of complex C.
+ mln_fwd_citer_(complex<D>) fwd_f(c);
+ for_all(fwd_f)
+ std::cout << fwd_f << std::endl;
std::cout << std::endl;
- mln_bkd_citer_(complex<D>) bf(c);
- for_all(bf)
- std::cout << bf << std::endl;
+ mln_bkd_citer_(complex<D>) bkd_f(c);
+ for_all(bkd_f)
+ std::cout << bkd_f << std::endl;
/* FIXME: Exercice more iterators (see
milena/tests/core/complex_image.cc) and ticket #162
--
1.6.0.1
* mln/core/internal/complex_iter_base.hh: New.
* mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
Remove.
(mln::internal::complex_fwd_iter_<D>)
(mln::internal::complex_bkd_iter_<D>):
Inherit from mln::internal::complex_iter_base_.
Adjust.
* mln/core/faces_iter.hh (mln::internal::faces_iter_<N, D, E>):
Remove.
(mln::internal::faces_fwd_iter_<N, D>)
(mln::internal::faces_bkd_iter_<N, D>):
Inherit from mln::internal::complex_iter_base_.
Adjust.
* mln/core/face.hh (mln::face_handle<N, D>::n): New accessor.
(mln::face_handle<N, D>::complex_type)
(mln::any_face_handle<D>::complex_type):
New typedefs.
(mln::face_handle<N, D>::invalidate)
(mln::any_face_handle<D>::invalidate):
New methods.
---
milena/ChangeLog | 25 +++
milena/mln/core/complex_iter.hh | 219 ++----------------------
milena/mln/core/face.hh | 35 ++++
milena/mln/core/faces_iter.hh | 215 ++----------------------
milena/mln/core/internal/complex_iter_base.hh | 214 ++++++++++++++++++++++++
5 files changed, 310 insertions(+), 398 deletions(-)
create mode 100644 milena/mln/core/internal/complex_iter_base.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f164de6..f4629b7 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,30 @@
2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+ Factor (more) iterators on complexes and faces.
+
+ * mln/core/internal/complex_iter_base.hh: New.
+ * mln/core/complex_iter.hh (mln::internal::complex_iter_<D, E>):
+ Remove.
+ (mln::internal::complex_fwd_iter_<D>)
+ (mln::internal::complex_bkd_iter_<D>):
+ Inherit from mln::internal::complex_iter_base_.
+ Adjust.
+ * mln/core/faces_iter.hh (mln::internal::faces_iter_<N, D, E>):
+ Remove.
+ (mln::internal::faces_fwd_iter_<N, D>)
+ (mln::internal::faces_bkd_iter_<N, D>):
+ Inherit from mln::internal::complex_iter_base_.
+ Adjust.
+ * mln/core/face.hh (mln::face_handle<N, D>::n): New accessor.
+ (mln::face_handle<N, D>::complex_type)
+ (mln::any_face_handle<D>::complex_type):
+ New typedefs.
+ (mln::face_handle<N, D>::invalidate)
+ (mln::any_face_handle<D>::invalidate):
+ New methods.
+
+2008-09-12 Roland Levillain <roland(a)lrde.epita.fr>
+
Add iterators on the n-faces of a complex.
* mln/core/faces_iter.hh: New.
diff --git a/milena/mln/core/complex_iter.hh b/milena/mln/core/complex_iter.hh
index 4aa9b99..3dcb445 100644
--- a/milena/mln/core/complex_iter.hh
+++ b/milena/mln/core/complex_iter.hh
@@ -31,95 +31,11 @@
/// \file mln/core/complex_iter.hh
/// \brief Definition of forward and backward iterators on complexes.
-# include <limits>
-
-# include <mln/core/concept/iterator.hh>
-# include <mln/core/complex.hh>
+# include <mln/core/internal/complex_iter_base.hh>
namespace mln
{
- // Fwd decls.
- template <unsigned D> class complex;
-
- /*--------------------------------.
- | internal::complex_iter_<D, E>. |
- `--------------------------------*/
-
- namespace internal
- {
- /// \brief Factoring classe for iterators on all the faces of
- /// a mln::complex<D>.
- ///
- /// \arg \p D The dimension of the complex this iterator belongs to.
- /// \arg \p E The type exact type of the iterator.
- template <unsigned D, typename E>
- class complex_iter_ : public Iterator<E>
- {
- typedef complex_iter_<D, E> self_;
-
- public:
- typedef any_face_handle<D> face;
-
- /// Construction and assignment.
- /// \{
- complex_iter_();
- /* FIXME: Keep this non-const? See a (big) comment about this in
- milena/tests/complex_image.cc. */
- complex_iter_(complex<D>& c);
- complex_iter_(const self_& rhs);
- self_& operator= (const self_& rhs);
- /// \}
-
- /// Manipulation.
- /// \{
- /// Test if the iterator is valid.
- bool is_valid() const;
- /// Invalidate the iterator.
- void invalidate();
- /// \}
-
- /// Conversion and accessors.
- /// \{
- /// Reference to the corresponding any-face handle.
- const face& to_face () const;
- /// Convert the iterator into an any-face handle.
- operator face() const;
- /// \}
-
- protected:
- /// The face handle this iterator is pointing to.
- face face_;
-
- private:
- /// \brief An invalid value for both the dimension and the id of
- /// the face.
- ///
- /// Use a function instead of a static constant, since `static'
- /// variables needs to be compiled once, which requires a compiled
- /// library to avoid duplicate symbols, which is something that
- /// was not really planned in Milena. A function tagged `inlined'
- /// can appear multiple times in a program, and solves this
- /// problem. We rely on the compiler to inline this call.
- ///
- /// Of course, we could have used UINT_MAX, but it is not very
- /// C++.
- unsigned invalid_unsigned_() const;
- };
-
-
- /* FIXME: This hand-made delegation is painful. We should rely on
- the general mechanism provided by Point_Site. But then again, we
- need to refine/adjust the interface of Point_Site w.r.t. the
- mandatory conversions to points. */
- template <unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_iter_<D, E>& p);
-
- } // end of mln::internal
-
-
/*-----------------------.
| complex_fwd_iter_<D>. |
`-----------------------*/
@@ -129,10 +45,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned D>
class complex_fwd_iter_
- : public internal::complex_iter_< D, complex_fwd_iter_<D> >
+ : public internal::complex_iter_base_< any_face_handle<D>,
+ complex_fwd_iter_<D> >
{
+ public:
+ typedef any_face_handle<D> face;
+
+ private:
typedef complex_fwd_iter_<D> self_;
- typedef internal::complex_iter_< D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -142,7 +63,7 @@ namespace mln
/// Construction and assignment.
/// \{
complex_fwd_iter_();
- // FIXME: See above (internal::complex_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
complex_fwd_iter_(complex<D>& c);
complex_fwd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -174,10 +95,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned D>
class complex_bkd_iter_
- : public internal::complex_iter_< D, complex_bkd_iter_<D> >
+ : public internal::complex_iter_base_< any_face_handle<D>,
+ complex_bkd_iter_<D> >
{
+ public:
+ typedef any_face_handle<D> face;
+
+ private:
typedef complex_bkd_iter_<D> self_;
- typedef internal::complex_iter_< D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -187,7 +113,7 @@ namespace mln
/// Construction and assignment.
/// \{
complex_bkd_iter_();
- // FIXME: See above (internal::complex_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
complex_bkd_iter_(complex<D>& c);
complex_bkd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -213,113 +139,6 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
- /*--------------------------------.
- | internal::complex_iter_<D, E>. |
- `--------------------------------*/
-
- namespace internal
- {
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::complex_iter_()
- {
- // Invalidate face_.
- invalidate();
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::complex_iter_(complex<D>& c)
- {
- face_.set_cplx(c);
- // Invalidate face_.
- invalidate();
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::complex_iter_(const complex_iter_<D, E>& rhs)
- : face_(rhs.face_)
- {
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>&
- complex_iter_<D, E>::operator=(const complex_iter_<D, E>& rhs)
- {
- if (&rhs == this)
- return *this;
- face_ = rhs.face_;
- return *this;
- }
-
- template <unsigned D, typename E>
- inline
- bool
- complex_iter_<D, E>::is_valid() const
- {
- return face_.is_valid();
- }
-
- template <unsigned D, typename E>
- inline
- void
- complex_iter_<D, E>::invalidate()
- {
- face_.set_n(invalid_unsigned_());
- face_.set_face_id(invalid_unsigned_());
- }
-
- template <unsigned D, typename E>
- inline
- const any_face_handle<D>&
- complex_iter_<D, E>::to_face() const
- {
- return face_;
- }
-
- template <unsigned D, typename E>
- inline
- complex_iter_<D, E>::operator any_face_handle<D>() const
- {
- mln_precondition(is_valid());
- return face_;
- }
-
- template <unsigned D, typename E>
- unsigned
- complex_iter_<D, E>::invalid_unsigned_() const
- {
- return std::numeric_limits<unsigned>::max();
- }
-
- template <unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const complex_iter_<D, E>& p)
- {
- /* FIXME: We should use p.to_face() here, but as it lacks the
- precondition the conversion operator has, so we use the latter.
-
- We should
- - rename `to_face' as `to_face_';
- - write a new `to_face' routine checking the validity of the
- iterator;
- - have the conversion operator to face use this new `to_face'
- routine;
- - adjust former clients of `to_face'
-
- This is a general remark that applies to all iterators of
- Milena. */
- any_face_handle<D> f = p;
- return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')';
- }
-
- } // end of mln::internal
-
-
/*-----------------------.
| complex_fwd_iter_<D>. |
`-----------------------*/
@@ -334,6 +153,7 @@ namespace mln
template <unsigned D>
inline
complex_fwd_iter_<D>::complex_fwd_iter_(complex<D>& c)
+ : super_(c)
{
set_cplx(c);
mln_postcondition(!is_valid());
@@ -413,8 +233,6 @@ namespace mln
| complex_bkd_iter_<D>. |
`-----------------------*/
- // FIXME: Resume here.
-
template <unsigned D>
inline
complex_bkd_iter_<D>::complex_bkd_iter_()
@@ -425,6 +243,7 @@ namespace mln
template <unsigned D>
inline
complex_bkd_iter_<D>::complex_bkd_iter_(complex<D>& c)
+ : super_(c)
{
set_cplx(c);
mln_postcondition(!is_valid());
diff --git a/milena/mln/core/face.hh b/milena/mln/core/face.hh
index 4e8e958..9fd685a 100644
--- a/milena/mln/core/face.hh
+++ b/milena/mln/core/face.hh
@@ -143,6 +143,9 @@ namespace mln
template <unsigned N, unsigned D>
struct face_handle
{
+ // The type of the complex this handle points to.
+ typedef complex<D> complex_type;
+
/// Build a non-initialized face handle.
face_handle();
/// Build a face handle from \a complex and \a face_id.
@@ -156,6 +159,8 @@ namespace mln
/// Is this handle valid?
bool is_valid() const;
+ /// Invalidate this handle.
+ void invalidate();
/// Accessors.
/// \{
@@ -167,6 +172,9 @@ namespace mln
/// Set the complex the face belongs to.
void set_cplx(complex<D>& cplx);
+ /// Return the dimension of the face.
+ // FIXME: Rename as `dim'?
+ unsigned n() const;
/// Set the id of the face.
void set_face_id(unsigned face_id);
@@ -259,6 +267,9 @@ namespace mln
template <unsigned D>
struct any_face_handle
{
+ // The type of the complex this handle points to.
+ typedef complex<D> complex_type;
+
/// Build a non-initialized face handle.
any_face_handle();
/// Build a face handle from \a complex and \a face_id.
@@ -276,6 +287,8 @@ namespace mln
/// Is this handle valid?
bool is_valid() const;
+ /// Invalidate this handle.
+ void invalidate();
/// Accessors.
/// \{
@@ -411,6 +424,13 @@ namespace mln
}
template <unsigned N, unsigned D>
+ void
+ face_handle<N, D>::invalidate()
+ {
+ set_face_id(std::numeric_limits<unsigned>::max());
+ }
+
+ template <unsigned N, unsigned D>
complex<D>&
face_handle<N, D>::cplx() const
{
@@ -420,6 +440,13 @@ namespace mln
template <unsigned N, unsigned D>
unsigned
+ face_handle<N, D>::n() const
+ {
+ return N;
+ }
+
+ template <unsigned N, unsigned D>
+ unsigned
face_handle<N, D>::face_id() const
{
return face_id_;
@@ -574,6 +601,14 @@ namespace mln
}
template <unsigned D>
+ void
+ any_face_handle<D>::invalidate()
+ {
+ set_n(std::numeric_limits<unsigned>::max());
+ set_face_id(std::numeric_limits<unsigned>::max());
+ }
+
+ template <unsigned D>
complex<D>&
any_face_handle<D>::cplx() const
{
diff --git a/milena/mln/core/faces_iter.hh b/milena/mln/core/faces_iter.hh
index 25dd2c2..e11073d 100644
--- a/milena/mln/core/faces_iter.hh
+++ b/milena/mln/core/faces_iter.hh
@@ -32,99 +32,11 @@
/// \brief Definition of forward and backward iterators on the n-faces
/// of a complex.
-# include <limits>
-
-# include <mln/core/concept/iterator.hh>
-# include <mln/core/complex.hh>
+# include <mln/core/internal/complex_iter_base.hh>
namespace mln
{
- // Fwd decls.
- template <unsigned D> class complex;
-
- /*---------------------------------.
- | internal::faces_iter_<N, D, E>. |
- `---------------------------------*/
-
- // FIXME: Maybe we should have a `face' parameter instead of N & D.
- // This way, we could merge this class and
- // internal::complex_iter_x<D, E>.
-
- namespace internal
- {
- /// \brief Factoring classe for iterators on all the \p N-faces of
- /// a mln::complex<D>.
- ///
- /// \arg \p N The dimension of the face associated to this iterator.
- /// \arg \p D The dimension of the complex this iterator belongs to.
- /// \arg \p E The type exact type of the iterator.
- template <unsigned N, unsigned D, typename E>
- class faces_iter_ : public Iterator<E>
- {
- typedef faces_iter_<N, D, E> self_;
-
- public:
- typedef face_handle<N, D> face;
-
- /// Construction and assignment.
- /// \{
- /* FIXME: Keep this non-const? See a (big) comment about this in
- milena/tests/complex_image.cc. */
- faces_iter_(complex<D>& c);
- faces_iter_(const self_& rhs);
- self_& operator= (const self_& rhs);
- /// \}
-
- /// Manipulation.
- /// \{
- /// Test if the iterator is valid.
- bool is_valid() const;
- /// Invalidate the iterator.
- void invalidate();
- /// \}
-
- /// Conversion and accessors.
- /// \{
- /// Reference to the corresponding face handle.
- const face& to_face () const;
- /// Convert the iterator into an face handle.
- operator face() const;
- /// \}
-
- protected:
- /// The face handle this iterator is pointing to.
- face face_;
-
- private:
- /// \brief An invalid value for both the dimension and the id of
- /// the face.
- ///
- /// Use a function instead of a static constant, since `static'
- /// variables needs to be compiled once, which requires a compiled
- /// library to avoid duplicate symbols, which is something that
- /// was not really planned in Milena. A function tagged `inlined'
- /// can appear multiple times in a program, and solves this
- /// problem. We rely on the compiler to inline this call.
- ///
- /// Of course, we could have used UINT_MAX, but it is not very
- /// C++.
- unsigned invalid_unsigned_() const;
- };
-
-
- /* FIXME: This hand-made delegation is painful. We should rely on
- the general mechanism provided by Point_Site. But then again, we
- need to refine/adjust the interface of Point_Site w.r.t. the
- mandatory conversions to points. */
- template <unsigned N, unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p);
-
- } // end of mln::internal
-
-
/*------------------------.
| faces_fwd_iter_<N, D>. |
`------------------------*/
@@ -135,10 +47,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned N, unsigned D>
class faces_fwd_iter_
- : public internal::faces_iter_< N, D, faces_fwd_iter_<N, D> >
+ : public internal::complex_iter_base_< face_handle<N, D>,
+ faces_fwd_iter_<N, D> >
{
+ public:
+ typedef face_handle<N, D> face;
+
+ private:
typedef faces_fwd_iter_<N, D> self_;
- typedef internal::faces_iter_< N, D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -147,7 +64,7 @@ namespace mln
public:
/// Construction and assignment.
/// \{
- // FIXME: See above (internal::faces_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
faces_fwd_iter_(complex<D>& c);
faces_fwd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -176,10 +93,15 @@ namespace mln
/// \arg \p D The dimension of the complex this iterator belongs to.
template <unsigned N, unsigned D>
class faces_bkd_iter_
- : public internal::faces_iter_< N, D, faces_bkd_iter_<N, D> >
+ : public internal::complex_iter_base_< face_handle<N, D>,
+ faces_bkd_iter_<N, D> >
{
+ public:
+ typedef face_handle<N, D> face;
+
+ private:
typedef faces_bkd_iter_<N, D> self_;
- typedef internal::faces_iter_< N, D, self_ > super_;
+ typedef internal::complex_iter_base_< face, self_ > super_;
public:
using super_::is_valid;
@@ -188,7 +110,7 @@ namespace mln
public:
/// Construction and assignment.
/// \{
- // FIXME: See above (internal::faces_iter_'s default ctor).
+ // FIXME: See above (internal::complex_iter_base_'s default ctor).
faces_bkd_iter_(complex<D>& c);
faces_bkd_iter_(const self_& rhs);
self_& operator= (const self_& rhs);
@@ -210,109 +132,6 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
- /*---------------------------------.
- | internal::faces_iter_<N, D, E>. |
- `---------------------------------*/
-
- namespace internal
- {
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>::faces_iter_(complex<D>& c)
- {
- // Ensure N is compatible with D.
- metal::bool_< N <= D >::check();
-
- face_.set_cplx(c);
- // Invalidate face_.
- invalidate();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>::faces_iter_(const faces_iter_<N, D, E>& rhs)
- : face_(rhs.face_)
- {
- // Ensure N is compatible with D.
- metal::bool_< N <= D >::check();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>&
- faces_iter_<N, D, E>::operator=(const faces_iter_<N, D, E>& rhs)
- {
- if (&rhs == this)
- return *this;
- face_ = rhs.face_;
- return *this;
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- bool
- faces_iter_<N, D, E>::is_valid() const
- {
- return face_.is_valid();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- void
- faces_iter_<N, D, E>::invalidate()
- {
- face_.set_face_id(invalid_unsigned_());
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- const face_handle<N, D>&
- faces_iter_<N, D, E>::to_face() const
- {
- return face_;
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- faces_iter_<N, D, E>::operator face_handle<N, D>() const
- {
- mln_precondition(is_valid());
- return face_;
- }
-
- template <unsigned N, unsigned D, typename E>
- unsigned
- faces_iter_<N, D, E>::invalid_unsigned_() const
- {
- return std::numeric_limits<unsigned>::max();
- }
-
- template <unsigned N, unsigned D, typename E>
- inline
- std::ostream&
- operator<<(std::ostream& ostr, const faces_iter_<N, D, E>& p)
- {
- /* FIXME: We should use p.to_face() here, but as it lacks the
- precondition the conversion operator has, so we use the latter.
-
- We should
- - rename `to_face' as `to_face_';
- - write a new `to_face' routine checking the validity of the
- iterator;
- - have the conversion operator to face use this new `to_face'
- routine;
- - adjust former clients of `to_face'
-
- This is a general remark that applies to all iterators of
- Milena. */
- typename faces_iter_<N, D, E>::face f = p;
- return ostr << "(dim = " << N << ", id = " << f.face_id() << ')';
- }
-
- } // end of mln::internal
-
-
/*------------------------.
| faces_fwd_iter_<N, D>. |
`------------------------*/
diff --git a/milena/mln/core/internal/complex_iter_base.hh b/milena/mln/core/internal/complex_iter_base.hh
new file mode 100644
index 0000000..df9b39a
--- /dev/null
+++ b/milena/mln/core/internal/complex_iter_base.hh
@@ -0,0 +1,214 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH
+# define MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH
+
+/// \file mln/core/complex_iter_base.hh
+/// \brief Definition of an implementation (factoring) class for
+/// iterators on complexes.
+
+# include <limits>
+
+# include <mln/metal/equal.hh>
+
+# include <mln/core/concept/iterator.hh>
+# include <mln/core/complex.hh>
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <unsigned D> class complex;
+
+ namespace internal
+ {
+ /// \brief Factoring classe for iterators on complexes.
+ ///
+ /// \arg \p F The type of the face handle.
+ /// \arg \p E The type exact type of the iterator.
+ template <typename F, typename E>
+ class complex_iter_base_ : public Iterator<E>
+ {
+ typedef complex_iter_base_<F, E> self_;
+
+ public:
+ typedef F face;
+ typedef typename F::complex_type complex_type;
+
+ /// Construction and assignment.
+ /// \{
+ /* FIXME: Keep this non-const? See a (big) comment about this in
+ milena/tests/complex_image.cc. */
+ complex_iter_base_();
+ complex_iter_base_(complex_type& c);
+ complex_iter_base_(const self_& rhs);
+ self_& operator= (const self_& rhs);
+ /// \}
+
+ /// Manipulation.
+ /// \{
+ /// Test if the iterator is valid.
+ bool is_valid() const;
+ /// Invalidate the iterator.
+ void invalidate();
+ /// \}
+
+ /// Conversion and accessors.
+ /// \{
+ /// Reference to the corresponding face handle.
+ const face& to_face () const;
+ /// Convert the iterator into an face handle.
+ operator face() const;
+ /// \}
+
+ protected:
+ /// The face handle this iterator is pointing to.
+ face face_;
+ };
+
+
+ /* FIXME: This hand-made delegation is painful. We should rely on
+ the general mechanism provided by Point_Site. But then again, we
+ need to refine/adjust the interface of Point_Site w.r.t. the
+ mandatory conversions to points. */
+ template <typename F, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const complex_iter_base_<F, E>& p);
+
+ } // end of mln::internal
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::complex_iter_base_()
+ {
+ // Ensure F and E are compatible.
+ mlc_equal(F, typename E::face)::check();
+
+ invalidate();
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::complex_iter_base_(complex_type& c)
+ {
+ // Ensure F and E are compatible.
+ mlc_equal(F, typename E::face)::check();
+
+ face_.set_cplx(c);
+ // Invalidate face_.
+ invalidate();
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::complex_iter_base_(const complex_iter_base_<F, E>& rhs)
+ : face_(rhs.face_)
+ {
+ // Ensure F and E are compatible.
+ mlc_equal(F, typename E::face)::check();
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>&
+ complex_iter_base_<F, E>::operator=(const complex_iter_base_<F, E>& rhs)
+ {
+ if (&rhs == this)
+ return *this;
+ face_ = rhs.face_;
+ return *this;
+ }
+
+ template <typename F, typename E>
+ inline
+ bool
+ complex_iter_base_<F, E>::is_valid() const
+ {
+ return face_.is_valid();
+ }
+
+ template <typename F, typename E>
+ inline
+ void
+ complex_iter_base_<F, E>::invalidate()
+ {
+ face_.invalidate();
+ }
+
+ template <typename F, typename E>
+ inline
+ const F&
+ complex_iter_base_<F, E>::to_face() const
+ {
+ return face_;
+ }
+
+ template <typename F, typename E>
+ inline
+ complex_iter_base_<F, E>::operator F() const
+ {
+ mln_precondition(is_valid());
+ return face_;
+ }
+
+
+ template <typename F, typename E>
+ inline
+ std::ostream&
+ operator<<(std::ostream& ostr, const complex_iter_base_<F, E>& p)
+ {
+ /* FIXME: We should use p.to_face() here, but as it lacks the
+ precondition the conversion operator has, so we use the latter.
+
+ We should
+ - rename `to_face' as `to_face_';
+ - write a new `to_face' routine checking the validity of the
+ iterator;
+ - have the conversion operator to face use this new `to_face'
+ routine;
+ - adjust former clients of `to_face'
+
+ This is a general remark that applies to all iterators of
+ Milena. */
+ F f = p;
+ return ostr << "(dim = " << f.n() << ", id = " << f.face_id() << ')';
+ }
+
+ } // end of mln::internal
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of mln
+
+#endif // ! MLN_CORE_INTERNAL_COMPLEX_ITER_BASE_HH
--
1.6.0.1