#3: Migrate Olena 0.11 (and previous revisions) from PRCS to Subversion
--------------------------+-------------------------------------------------
Reporter: levill_r | Owner: levill_r
Type: enhancement | Status: assigned
Priority: blocker | Milestone: Olena 0.11.1
Component: other | Version: 0.11
Resolution: | Keywords: prcs subversion svn
--------------------------+-------------------------------------------------
Comment (by anonymous):
default as a design pattern rather than trying to put it all together.
That way you can never create offline or print docs of high quality
without again having the devs or current admins maintain the comments and
annotations. Hopefully a small Wiki quality team will evolve (i am against
ops or admins) to review and summarize the contributions. I hope this
gives us more users as contributors than having the docs focused on the
devs. Cheers, duns [http://www.about-china.net.cn/wrought-iron/cat_4.html
china tour] [http://www.about-china.net.cn/wrought-iron/cat_3.html
Apparel] [http://www.about-china.net.cn/wrought-iron/cat_5.html shoes]
[http://www.about-china.net.cn/wrought-iron/cat_12.html bags] [http://www
.about-china.net.cn/wrought-iron/cat_6.html Kitchen] [http://www.about-
china.net.cn/wrought-iron/cat_7.html Food and Wine] [http://www.about-
china.net.cn/wrought-iron/cat_8.html Furniture)] [http://www.about-
china.net.cn/wrought-iron/cat_9.html Flowers and Gifts] [http://www.about-
china.net.cn/wrought-iron/cat_10.html Wall Art] [http://www.about-
china.net.cn/wrought-iron/cat_11.html Computer Components] I still prefer
a wiki like approach since the php (or mysql) docs are very cluttered when
you have to take their comments in account. On the other hand they are
professionally maintained imho, since they are *much* better than KDE
documentation. KDE is by far larger and has so many different apps, which
need screenshots and end user not dev/api docs, that more help is needed
as long as the devs prefer to code than to write nice docs. And it is
their choice to some degree imo. Technically interested but non-dev end
users, which are plenty out there, are the users of and the best
contributers to the docs
--
Ticket URL: <https://trac.lrde.org/olena/ticket/3#comment:6>
Olena <http://olena.lrde.epita.fr>
Olena, a generic and efficient C++ image processing library.
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
* mln/io/pnm/load.hh: Fix dates in copyright header.
load.hh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: mln/io/pnm/load.hh
--- mln/io/pnm/load.hh (revision 2254)
+++ mln/io/pnm/load.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 EPITA
-// Research and Development Laboratory
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 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
* 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