2399: Move complex-related entities to mln/topo/.

* mln/topo/: New directory. * tests/topo/: New directory. * mln/core/complex.hh, * mln/core/complex_faces_iter.hh, * mln/core/face.hh, * mln/core/faces_iter.hh, * mln/core/internal/complex_iter_base.hh, * tests/core/other/complex.cc: Move... * mln/topo/complex.hh, * mln/topo/complex_faces_iter.hh, * mln/topo/face.hh, * mln/topo/faces_iter.hh, * mln/topo/internal/complex_iter_base.hh, * tests/topo/complex.cc: ...here. Adjust. * tests/core/other/Makefile.am (check_PROGRAM): Remove complex. (complex_SOURCES): Remove. * tests/topo/Makefile.am: New. (check_PROGRAM): Add complex. (complex_SOURCES, TESTS): New. * tests/Makefile.am (SUBDIRS): Add topo. --- milena/ChangeLog | 29 + milena/mln/core/complex.hh | 853 ------------------------ milena/mln/core/complex_faces_iter.hh | 262 -------- milena/mln/core/complex_iter.hh | 270 -------- milena/mln/core/face.hh | 729 --------------------- milena/mln/core/faces_iter.hh | 247 ------- milena/mln/core/internal/complex_iter_base.hh | 202 ------ milena/mln/topo/complex.hh | 857 +++++++++++++++++++++++++ milena/mln/topo/complex_faces_iter.hh | 266 ++++++++ milena/mln/topo/complex_iter.hh | 275 ++++++++ milena/mln/topo/face.hh | 733 +++++++++++++++++++++ milena/mln/topo/faces_iter.hh | 251 ++++++++ milena/mln/topo/internal/complex_iter_base.hh | 208 ++++++ milena/tests/Makefile.am | 1 + milena/tests/core/other/Makefile.am | 2 - milena/tests/topo/Makefile.am | 10 + milena/tests/{core/other => topo}/complex.cc | 54 +- 17 files changed, 2657 insertions(+), 2592 deletions(-) delete mode 100644 milena/mln/core/complex.hh delete mode 100644 milena/mln/core/complex_faces_iter.hh delete mode 100644 milena/mln/core/complex_iter.hh delete mode 100644 milena/mln/core/face.hh delete mode 100644 milena/mln/core/faces_iter.hh delete mode 100644 milena/mln/core/internal/complex_iter_base.hh create mode 100644 milena/mln/topo/complex.hh create mode 100644 milena/mln/topo/complex_faces_iter.hh create mode 100644 milena/mln/topo/complex_iter.hh create mode 100644 milena/mln/topo/face.hh create mode 100644 milena/mln/topo/faces_iter.hh create mode 100644 milena/mln/topo/internal/complex_iter_base.hh create mode 100644 milena/tests/topo/Makefile.am rename milena/tests/{core/other => topo}/complex.cc (79%) diff --git a/milena/ChangeLog b/milena/ChangeLog index aa7dc82..0963983 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,32 @@ +2008-09-24 Roland Levillain <roland@lrde.epita.fr> + + Move complex-related entities to mln/topo/. + + * mln/topo/: New directory. + * tests/topo/: New directory. + * mln/core/complex.hh, + * mln/core/complex_faces_iter.hh, + * mln/core/face.hh, + * mln/core/faces_iter.hh, + * mln/core/internal/complex_iter_base.hh, + * tests/core/other/complex.cc: + Move... + * mln/topo/complex.hh, + * mln/topo/complex_faces_iter.hh, + * mln/topo/face.hh, + * mln/topo/faces_iter.hh, + * mln/topo/internal/complex_iter_base.hh, + * tests/topo/complex.cc: + ...here. + Adjust. + * tests/core/other/Makefile.am + (check_PROGRAM): Remove complex. + (complex_SOURCES): Remove. + * tests/topo/Makefile.am: New. + (check_PROGRAM): Add complex. + (complex_SOURCES, TESTS): New. + * tests/Makefile.am (SUBDIRS): Add topo. + 2008-09-24 Thierry Geraud <thierry.geraud@lrde.epita.fr> Make w_window tests pass with from_to instead of to_w_window. diff --git a/milena/mln/core/complex.hh b/milena/mln/core/complex.hh deleted file mode 100644 index 2329a71..0000000 --- a/milena/mln/core/complex.hh +++ /dev/null @@ -1,853 +0,0 @@ -// 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_COMPLEX_HH -# define MLN_CORE_COMPLEX_HH - -/// \file mln/core/complex.hh -/// \brief Structures for general complexes. -/// -/// A complex defines a topological space which can be used as a -/// support for an image (i.e., as site sets). - -# include <cstddef> - -# include <limits> -# include <iosfwd> - -# include <mln/metal/bool.hh> - -# include <mln/util/tracked_ptr.hh> - -# include <mln/core/face.hh> - -# include <mln/core/complex_iter.hh> -# include <mln/core/faces_iter.hh> -# include <mln/core/complex_faces_iter.hh> - - -namespace mln -{ - - // Forward declarations. - namespace internal - { - template <unsigned D> - struct complex_data; - - template <unsigned N, unsigned D> - struct faces_set_mixin; - } - 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_; - - - /*----------. - | Complex. | - `----------*/ - - /// \brief General complex of dimension \p D. - template <unsigned D> - class complex - { - public: - /// Forward mln::Iterator type iterating on all faces. - typedef complex_fwd_iter_<D> fwd_citer; - /// 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. - /// \{ - /// Create a new \p D-complex. - complex(); - - /// \brief Add a 0-face to the complex. - face_handle<0u, D> add_face(); - - /// \brief Add a \p (N+1)-face to the complex (with \p N >= 0). - /// - /// \param adjacent_faces The (\p N-1)-faces adjacent to the new - /// \p N-face. - template <unsigned N> - face_handle<N + 1, D> add_face(const faces_set<N, D>& adjacent_faces); - /// \} - - /// \brief Static manipulators. - /// - /// These methods use statically-known input. - /// \{ - /// \brief Return the total number of faces, whatever their - /// dimension. - std::size_t nfaces() const; - - /// \brief Return the number of \p N-faces. - template <unsigned N> - std::size_t nfaces() const; - /// \} - - /// \brief Dynamic manipulators. - /// - /// These methods use input know as run time. - /// \{ - /// \brief Return the number of \a n-faces. - /// - /// Warning, this function has a complexity linear in term of N, - /// since each faces_set is checked (the present implementation - /// does not provide a direct access to faces_set through a - /// dynamic value of the dimension). - std::size_t nfaces(unsigned n) const; - /// \} - - /// Pretty-printing. - /// \{ - /// Print the complex. - void print(std::ostream& ostr) const; - /// Print the faces of dimension \p N. - template <unsigned N> - void print_faces(std::ostream& ostr) const; - /// \} - - private: - /// The actual data of the complex. - util::tracked_ptr< internal::complex_data<D> > data_; - - template <unsigned D_> - friend bool operator==(const complex<D_>& lhs, const complex<D_>& rhs); - - /// Accessors. - /// \{ - template <unsigned N, unsigned D_> friend class face_handle; - template <unsigned D_> friend class any_face_handle; - - template <unsigned N> - face<N, D>& face_(unsigned face_id); - - template <unsigned N> - const face<N, D>& face_(unsigned face_id) const; - /// \} - - /// Functional meta-manipulators. - /// \{ - /* FIXME: Use something more constraining than the STL's - UnaryFunction/BinaryFunction. Use Function or Function_v2v? - Or a new subclass of Function? */ - - /* FIXME: Replace F and ACCU by a Milena accumulator? */ - - /** \brief Apply a kind of static fold left operator to the - implicit list of faces_set using a functor \a f and a value \a - accu. - - Argument \a is called an "accumulator", but with a slightly - different meaning than mln:accu members. - - We might want to use TypeLists or something similar, is they - provide an explicit static fold left operator. */ - template <typename BinaryFunction, typename T> - T fold_left_(const BinaryFunction& f, const T& accu) const; - - /// \brief Apply a functor \a f to this list of \a n-faces. - template <typename UnaryFunction> - typename UnaryFunction::result_type - apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; - /// \} - - /// \brief connect two faces. - /// - /// \param f1 A face of dimension \p N - /// \param f2 A face of dimension \p N + 1 - /// - /// \pre \p N must be lower or equal to \p D. - template <unsigned N> - void connect_(const face_handle<N, D>& f1, - const face_handle<N + 1, D>& f2); - }; - - - /// Compare two complexes for equality. - template <unsigned D> - bool - operator==(const complex<D>& lhs, const complex<D>& rhs); - - - /// Pretty print a complex. - template <unsigned D> - std::ostream& - operator<<(std::ostream& ostr, const complex<D>& c); - - - /*---------------. - | Complex data. | - `---------------*/ - - namespace internal - { - // Forward declarations. - template <unsigned N, unsigned D> - struct faces_set_mixin; - - /// \brief Complex data. - template <unsigned D> - struct complex_data : faces_set_mixin<D, D> - { - // Data is contained in super classes. - }; - - } // end of namespace mln::internal::complex - - - /*---------------------. - | Faces of a complex. | - `---------------------*/ - - /// The sets of n-faces of a complex are recursively aggregated as - /// mixins. - namespace internal - { - - // Forward declarations. - template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin; - template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin; - - // -------------------------------- // - // mln::internal::faces_set_mixin. // - // -------------------------------- // - - /// \brief Recursive mixins of set of faces. - /// \{ - template <unsigned N, unsigned D> struct faces_set_mixin; - - /// Faces of highest dimension (\p D). - template <unsigned D> - struct faces_set_mixin<D, D> : public faces_set_mixin<D - 1, D>, - public lower_dim_faces_set_mixin<D, D> - { - std::vector< face<D, D> > faces_; - - /// Pretty-printing. - /// \{ - /// Print the faces of dimension \p D. - void print(std::ostream& ostr) const; - void print_rec_asc(std::ostream& ostr) const; - /// \} - - /// Functional meta-manipulators. - /// \{ - /// \brief Fold left. - /// \see mln::complex<D>::fold_left_. - template <typename BinaryFunction, typename T> - T fold_left_(const BinaryFunction& f, const T& accu) const; - /// \brief Apply a functor \a f to the list of faces if \a n == \p D. - /// \see mln::complex<D>::apply_if_dim_matches_. - template <typename UnaryFunction> - typename UnaryFunction::result_type - apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; - /// \} - }; - - /// Faces of intermediate dimension (greater than 0, lower than \p D). - template <unsigned N, unsigned D> - struct faces_set_mixin : public faces_set_mixin<N - 1, D>, - public lower_dim_faces_set_mixin<N, D>, - public higher_dim_faces_set_mixin<N, D> - { - std::vector< face<N, D> > faces_; - - /// Pretty-printing. - /// \{ - /// Print the faces of dimension \p N. - void print(std::ostream& ostr) const; - /// Recursively print the faces of dimensions 0 to \p N - /// (in ascending dimension). - void print_rec_asc(std::ostream& ostr) const; - /// \} - - /// Functional meta-manipulators. - /// \{ - /// \brief Fold left. - /// \see mln::complex<D>::fold_left_. - template <typename BinaryFunction, typename T> - T fold_left_(const BinaryFunction& f, const T& accu) const; - /// \brief Apply a functor \a f to the list of faces if \a n == \p N. - /// \see mln::complex<D>::apply_if_dim_matches_. - template <typename UnaryFunction> - typename UnaryFunction::result_type - apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; - /// \} - }; - - /// Faces of lowest dimension (0). - template <unsigned D> - struct faces_set_mixin<0u, D> : public higher_dim_faces_set_mixin<0u, D> - { - std::vector< face<0u, D> > faces_; - - /// Pretty-printing. - /// \{ - /// Print the faces of dimension 0. - void print(std::ostream& ostr) const; - void print_rec_asc(std::ostream& ostr) const; - /// \} - - /// Functional meta-manipulators. - /// \{ - /// \brief Fold left. - /// \see mln::complex<D>::fold_left_. - template <typename BinaryFunction, typename T> - T fold_left_(const BinaryFunction& f, const T& accu) const; - /// \brief Apply a functor \a f to the list of faces if \a n == 0. - /// \see mln::complex<D>::apply_if_dim_matches_. - template <typename UnaryFunction> - typename UnaryFunction::result_type - apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; - /// \} - }; - - /// Faces of a 0-complex. - template <> - struct faces_set_mixin<0u, 0u> - { - std::vector< face<0u, 0u> > faces_; - - /// Pretty-printing. - /// \{ - /// Print the faces of dimension \p D. - void print(std::ostream& ostr) const; - void print_rec_asc(std::ostream& ostr) const; - /// \} - - /// Functional meta-manipulators. - /// \{ - /// \brief Fold left. - /// \see mln::complex<D>::fold_left_. - template <typename BinaryFunction, typename T> - T fold_left_(const BinaryFunction& f, const T& accu) const; - /// \brief Apply a functor \a f to the list of faces if \a n == 0. - /// \see mln::complex<D>::apply_if_dim_matches_. - template <typename UnaryFunction> - typename UnaryFunction::result_type - apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; - /// \} - }; - /// \} - - - // ------------------------------------------- // - // mln::internal::lower_dim_faces_set_mixin. // - // mln::internal::higher_dim_faces_set_mixin. // - // ------------------------------------------- // - - /// Mixins of mixin mln::faces_set_mixin. - /// \{ - template <unsigned N, unsigned D> - struct lower_dim_faces_set_mixin - { - void print(std::ostream& ostr, const face<N, D>& f) const; - }; - - template <unsigned N, unsigned D> - struct higher_dim_faces_set_mixin - { - void print(std::ostream& ostr, const face<N, D>& f) const; - }; - /// \} - - } // end of namespace mln::internal - - - -# ifndef MLN_INCLUDE_ONLY - - /*-----------------------. - | Complex construction. | - `-----------------------*/ - - template <unsigned D> - complex<D>::complex() - // Allocate data for this complex. - : data_(new internal::complex_data<D>()) - { - } - - template <unsigned D> - face_handle<0u, D> - complex<D>::add_face() - { - /* FIXME: This is not thread-proof (these two lines should - form an atomic section). */ - data_->internal::faces_set_mixin<0u, D>::faces_.push_back(face<0u, D>()); - unsigned id = nfaces<0u>() - 1; - - return face_handle<0u, D>(*this, id); - } - - template <unsigned D> - template <unsigned N> - face_handle<N + 1, D> - complex<D>::add_face(const faces_set<N, D>& adjacent_faces) - { - typedef typename std::vector< face_handle<N, D> >::const_iterator iter_t; - - // Ensure ADJACENT_FACES are already part of the complex. - if (!HAS_NDEBUG) - for (iter_t a = adjacent_faces.faces().begin(); - a != adjacent_faces.faces().end(); ++a) - { - mln_precondition(&a->cplx() == this); - mln_precondition(a->is_valid()); - } - - face<N + 1, D> f; - /* FIXME: This is not thread-proof (these two lines should - form an atomic section). */ - data_->internal::faces_set_mixin<N + 1, D>::faces_.push_back(f); - unsigned id = nfaces<N + 1>() - 1; - - face_handle<N + 1, D> fh(*this, id); - // Connect F and its ADJACENT_FACES. - for (iter_t a = adjacent_faces.faces().begin(); - a != adjacent_faces.faces().end(); ++a) - connect_(*a, fh); - return fh; - } - - - /*-------. - | Misc. | - `-------*/ - - namespace internal - { - - /// A binary meta-functor defined by: - /// - /// \code - /// add_size : x, c -> x + c.size() - /// \endcode - /// - /// \see mln::complex<D>::nfaces (static version). - /// \see mln::complex<D>::fold_left_. - struct add_size - { - template <typename T, typename Container> - T operator()(const T& x, const Container& c) const - { - return x + c.size(); - } - }; - - /// An unary meta-functor defined by: - /// - /// \code - /// add_size : c -> c.size() - /// \endcode - /// - /// \see mln::complex<D>::nfaces (dynamic version). - /// \see mln::complex<D>::apply_if_dim_matches_. - struct get_size - { - typedef std::size_t result_type; - - template <typename Container> - typename Container::size_type operator()(const Container& c) const - { - return c.size(); - } - }; - - } // end of namespace mln::internal - - - /*----------------------. - | Static manipulators. | - `----------------------*/ - - template <unsigned D> - std::size_t - complex<D>::nfaces() const - { - return fold_left_(internal::add_size(), 0); - } - - template <unsigned D> - template <unsigned N> - std::size_t - complex<D>::nfaces() const - { - return data_->internal::faces_set_mixin<N, D>::faces_.size(); - } - - - /*-----------------------. - | Dynamic manipulators. | - `-----------------------*/ - - template <unsigned D> - std::size_t - complex<D>::nfaces(unsigned n) const - { - // Ensure N is compatible with D. - mln_precondition(n <= D); - return apply_if_dim_matches_(n, internal::get_size()); - } - - - /*-------------------. - | Internal methods. | - `-------------------*/ - - template <unsigned D> - template <unsigned N> - face<N, D>& - complex<D>::face_(unsigned face_id) - { - return data_->internal::faces_set_mixin<N, D>::faces_[face_id]; - } - - template <unsigned D> - template <unsigned N> - const face<N, D>& - complex<D>::face_(unsigned face_id) const - { - return data_->internal::faces_set_mixin<N, D>::faces_[face_id]; - } - - template <unsigned D> - template <unsigned N> - void - complex<D>::connect_(const face_handle<N, D>& f1, - const face_handle<N + 1, D>& f2) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - - f1.to_face().connect_higher_dim_face(f2); - f2.to_face().connect_lower_dim_face(f1); - } - - - /*-------------. - | Comparison. | - `-------------*/ - - template <unsigned D> - bool - operator==(const complex<D>& lhs, const complex<D>& rhs) - { - return lhs.data_.ptr_ == rhs.data_.ptr_; - } - - - /*------------------. - | Pretty-printing. | - `------------------*/ - - template <unsigned D> - std::ostream& - operator<<(std::ostream& ostr, const complex<D>& c) - { - c.print(ostr); - return ostr; - } - - template <unsigned D> - void - complex<D>::print(std::ostream& ostr) const - { - data_->internal::faces_set_mixin<D, D>::print_rec_asc(ostr); - } - - template <unsigned D> - template <unsigned N> - void - complex<D>::print_faces(std::ostream& ostr) const - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - - data_->internal::faces_set_mixin<N, D>::print(ostr); - } - - - namespace internal - { - - template <unsigned N, unsigned D> - void - faces_set_mixin<N, D>::print_rec_asc(std::ostream& ostr) const - { - faces_set_mixin<N - 1, D>::print_rec_asc(ostr); - print(ostr); - } - - template <unsigned D> - void - faces_set_mixin<0u, D>::print_rec_asc(std::ostream& ostr) const - { - print(ostr); - } - - template <unsigned D> - void - faces_set_mixin<D, D>::print_rec_asc(std::ostream& ostr) const - { - faces_set_mixin<D - 1, D>::print_rec_asc(ostr); - print(ostr); - } - - void - faces_set_mixin<0u, 0u>::print_rec_asc(std::ostream& ostr) const - { - print(ostr); - } - - - template <unsigned N, unsigned D> - void - faces_set_mixin<N, D>::print(std::ostream& ostr) const - { - ostr << "Faces of dimension " << N - << " and their ajacent faces of dimension " - << N - 1 << " and " - << N + 1 << std::endl; - for (unsigned f = 0; f < faces_.size(); ++f) - { - ostr << " " << f << ": dim " << N - 1 << ": { "; - lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); - ostr << "}, dim " << N + 1 << ": { "; - higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); - ostr << "}" << std::endl; - } - } - - template <unsigned D> - void - faces_set_mixin<0u, D>::print(std::ostream& ostr) const - { - const unsigned N = 0u; - ostr << "Faces of dimension " << N - << " and their ajacent faces of dimension " - << N + 1 << std::endl; - for (unsigned f = 0; f < faces_.size(); ++f) - { - ostr << " " << f << ": dim " << N + 1 << ": { "; - higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); - ostr << "}" << std::endl; - } - } - - template <unsigned D> - void - faces_set_mixin<D, D>::print(std::ostream& ostr) const - { - const unsigned N = D; - ostr << "Faces of dimension " << N - << " and their ajacent faces of dimension " - << N - 1 << std::endl; - for (unsigned f = 0; f < faces_.size(); ++f) - { - ostr << " " << f << ": dim " << N - 1 << ": { "; - lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); - ostr << "}" << std::endl; - } - } - - void - faces_set_mixin<0u, 0u>::print(std::ostream& ostr) const - { - const unsigned N = 0u; - ostr << "Faces of dimension " << N << std::endl; - for (unsigned f = 0; f < faces_.size(); ++f) - ostr << " " << f << std::endl; - } - - - template <unsigned N, unsigned D> - void - lower_dim_faces_set_mixin<N, D>::print(std::ostream& ostr, - const face<N, D>& f) const - { - for (typename std::vector< face_handle<N - 1, D> >::const_iterator l = - f.lower_dim_faces_.begin(); l != f.lower_dim_faces_.end(); ++l) - ostr << l->face_id() << " "; - } - - template <unsigned N, unsigned D> - void - higher_dim_faces_set_mixin<N, D>::print(std::ostream& ostr, - const face<N, D>& f) const - { - for (typename std::vector< face_handle<N + 1, D> >::const_iterator h = - f.higher_dim_faces_.begin(); h != f.higher_dim_faces_.end(); ++h) - ostr << h->face_id() << " "; - } - - } // end of namespace mln::internal - - - /*-------------------------------. - | Functional meta-manipulators. | - `-------------------------------*/ - - /* ------------------------------- */ - /* ``Static Fold Left'' Operator. */ - /* ------------------------------- */ - - template <unsigned D> - template <typename BinaryFunction, typename T> - T - complex<D>::fold_left_(const BinaryFunction& f, const T& accu) const - { - return data_->internal::faces_set_mixin<D, D>::fold_left_(f, accu); - } - - namespace internal - { - - // FIXME: Try to factor. - - template <unsigned D> - template <typename BinaryFunction, typename T> - T - faces_set_mixin<D, D>::fold_left_(const BinaryFunction& f, - const T& accu) const - { - return faces_set_mixin<D - 1, D>::fold_left_(f, f(accu, faces_)); - } - - template <unsigned N, unsigned D> - template <typename BinaryFunction, typename T> - T - faces_set_mixin<N, D>::fold_left_(const BinaryFunction& f, - const T& accu) const - { - return faces_set_mixin<N - 1, D>::fold_left_(f, f(accu, faces_)); - } - - template <unsigned D> - template <typename BinaryFunction, typename T> - T - faces_set_mixin<0u, D>::fold_left_(const BinaryFunction& f, - const T& accu) const - { - return f(accu, faces_); - } - - template <typename BinaryFunction, typename T> - T - faces_set_mixin<0u, 0u>::fold_left_(const BinaryFunction& f, - const T& accu) const - { - return f(accu, faces_); - } - - } // end of namespace mln::internal - - - /* ------------------------------------------------ */ - /* ``Static Apply-If-Dimension-Matches'' Operator. */ - /* ------------------------------------------------ */ - - template <unsigned D> - template <typename UnaryFunction> - typename UnaryFunction::result_type - complex<D>::apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const - { - // Ensure N is compatible with D. - mln_precondition(n <= D); - return data_->internal::faces_set_mixin<D, D>::apply_if_dim_matches_(n, f); - } - - namespace internal - { - - // FIXME: Try to factor. - - template <unsigned D> - template <typename UnaryFunction> - typename UnaryFunction::result_type - faces_set_mixin<D, D>::apply_if_dim_matches_(unsigned n, - const UnaryFunction& f) const - { - // Ensure N and D are compatible. - mln_precondition(n <= D); - return n == D ? - f(faces_) : - faces_set_mixin<D - 1, D>::apply_if_dim_matches_(n, f); - } - - template <unsigned N, unsigned D> - template <typename UnaryFunction> - typename UnaryFunction::result_type - faces_set_mixin<N, D>::apply_if_dim_matches_(unsigned n, - const UnaryFunction& f) const - { - // Ensure N and D are compatible. - mln_precondition(n <= D); - return n == N ? - f(faces_) : - faces_set_mixin<N - 1, D>::apply_if_dim_matches_(n, f); - } - - template <unsigned D> - template <typename UnaryFunction> - typename UnaryFunction::result_type - faces_set_mixin<0u, D>::apply_if_dim_matches_(unsigned n, - const UnaryFunction& f) const - { - // If we reached this method, then N should be 0. - mln_precondition(n == 0); - return f(faces_); - } - - template <typename UnaryFunction> - typename UnaryFunction::result_type - faces_set_mixin<0u, 0u>::apply_if_dim_matches_(unsigned n, - const UnaryFunction& f) const - { - // If we reached this method, then N should be 0. - mln_precondition(n == 0); - return f(faces_); - } - - } // end of namespace mln::internal - -# endif // ! MLN_INCLUDE_ONLY - -} // end of namespace mln - - -#endif // ! MLN_CORE_COMPLEX_HH diff --git a/milena/mln/core/complex_faces_iter.hh b/milena/mln/core/complex_faces_iter.hh deleted file mode 100644 index ea86f6f..0000000 --- a/milena/mln/core/complex_faces_iter.hh +++ /dev/null @@ -1,262 +0,0 @@ -// 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_COMPLEX_FACES_ITER_HH -# define MLN_CORE_COMPLEX_FACES_ITER_HH - -/// \file mln/core/complex_faces_iter.hh -/// \brief Definition of forward and backward iterators on the n-faces -/// of a complex. - -# include <mln/core/internal/complex_iter_base.hh> - -/* FIXME: Should we drop N from the signature of these iterators? - I.e., have N be dynamic? Or better: provide other iterators where - N is dynamic? */ - - -namespace mln -{ - - /*--------------------------------. - | complex_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 complex_faces_fwd_iter_ - : public internal::complex_iter_base_< any_face_handle<D>, - complex_faces_fwd_iter_<N, D> > - { - public: - /// Type of associated face. - typedef any_face_handle<D> face; - - private: - typedef complex_faces_fwd_iter_<N, D> self_; - typedef internal::complex_iter_base_< face, self_ > super_; - - public: - using super_::is_valid; - using super_::invalidate; - - public: - /// Construction and assignment. - /// \{ - complex_faces_fwd_iter_(); - // FIXME: See comment in internal::complex_iter_base_'s default ctor - complex_faces_fwd_iter_(complex<D>& c); - /// \} - - /// Manipulation. - /// \{ - /// Test if the iterator is valid. - void start(); - /// Go to the next point. - void next_(); - /// \} - - private: - using super_::face_; - }; - - - /*--------------------------------. - | complex_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 complex_faces_bkd_iter_ - : public internal::complex_iter_base_< any_face_handle<D>, - complex_faces_bkd_iter_<N, D> > - { - public: - /// Type of associated face. - typedef any_face_handle<D> face; - - private: - typedef complex_faces_bkd_iter_<N, D> self_; - typedef internal::complex_iter_base_< face, self_ > super_; - - public: - using super_::is_valid; - using super_::invalidate; - - public: - /// Construction and assignment. - /// \{ - complex_faces_bkd_iter_(); - // FIXME: See comment in internal::complex_iter_base_'s default ctor - complex_faces_bkd_iter_(complex<D>& c); - /// \} - - /// Manipulation. - /// \{ - /// Start an iteration. - void start(); - /// Go to the next point. - void next_(); - /// \} - - private: - using super_::face_; - }; - - - -# ifndef MLN_INCLUDE_ONLY - - /*--------------------------------. - | complex_faces_fwd_iter_<N, D>. | - `--------------------------------*/ - - template <unsigned N, unsigned D> - inline - complex_faces_fwd_iter_<N, D>::complex_faces_fwd_iter_() - : super_() - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - face_.set_n(N); - mln_postcondition(!is_valid()); - } - - template <unsigned N, unsigned D> - inline - complex_faces_fwd_iter_<N, D>::complex_faces_fwd_iter_(complex<D>& c) - : super_(c) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - face_.set_n(N); - mln_postcondition(!is_valid()); - } - - template <unsigned N, unsigned D> - inline - void - complex_faces_fwd_iter_<N, D>::start() - { - face_.set_face_id(0u); - } - - template <unsigned N, unsigned D> - inline - void - complex_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 any_face_handle::face_id() - returning a mutable reference? This way, we could just - write - - ++face_.face_id(); - - instead of the following. - - Or add {inc,add}_face_id() services. */ - face_.set_face_id(face_id + 1); - else - invalidate(); - } - } - - - /*--------------------------------. - | complex_faces_bkd_iter_<N, D>. | - `--------------------------------*/ - - template <unsigned N, unsigned D> - inline - complex_faces_bkd_iter_<N, D>::complex_faces_bkd_iter_() - : super_() - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - face_.set_n(N); - mln_postcondition(!is_valid()); - } - - template <unsigned N, unsigned D> - inline - complex_faces_bkd_iter_<N, D>::complex_faces_bkd_iter_(complex<D>& c) - : super_(c) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - face_.set_n(N); - mln_postcondition(!is_valid()); - } - - template <unsigned N, unsigned D> - inline - void - complex_faces_bkd_iter_<N, D>::start() - { - face_.set_face_id(face_.cplx().template nfaces<N>() - 1); - } - - template <unsigned N, unsigned D> - inline - void - complex_faces_bkd_iter_<N, D>::next_() - { - if (is_valid()) - { - unsigned face_id = face_.face_id(); - if (face_id > 0) - /* FIXME: Provide accessor any_face_handle::face_id() - returning a mutable reference? This way, we could just - write - - ++face_.face_id(); - - instead of the following. - - Or add {inc,add}_face_id() services. */ - face_.set_face_id(face_id - 1); - else - invalidate(); - } - } - -# endif // ! MLN_INCLUDE_ONLY - -} // end of mln - - -#endif // ! MLN_CORE_COMPLEX_FACES_ITER_HH diff --git a/milena/mln/core/complex_iter.hh b/milena/mln/core/complex_iter.hh deleted file mode 100644 index 2a486be..0000000 --- a/milena/mln/core/complex_iter.hh +++ /dev/null @@ -1,270 +0,0 @@ -// 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_COMPLEX_ITER_HH -# define MLN_CORE_COMPLEX_ITER_HH - -/// \file mln/core/complex_iter.hh -/// \brief Definition of forward and backward iterators on complexes. - -# include <mln/core/internal/complex_iter_base.hh> - -// FIXME: Factor a bit more? (Using complex_iter_base_.) - - -namespace mln -{ - - // Forward declaration. - template <unsigned D> class complex; - - /*-----------------------. - | complex_fwd_iter_<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 internal::complex_iter_base_< any_face_handle<D>, - complex_fwd_iter_<D> > - { - public: - /// Type of associated face. - typedef any_face_handle<D> face; - - private: - typedef complex_fwd_iter_<D> self_; - typedef internal::complex_iter_base_< face, self_ > super_; - - public: - using super_::is_valid; - using super_::invalidate; - - public: - /// Construction and assignment. - /// \{ - complex_fwd_iter_(); - // FIXME: See comment in internal::complex_iter_base_'s default ctor - complex_fwd_iter_(complex<D>& c); - /// \} - - /// Manipulation. - /// \{ - /// Test if the iterator is valid. - void start(); - /// Go to the next point. - void next_(); - /// \} - - private: - using super_::face_; - }; - - - /*-----------------------. - | complex_bkd_iter_<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 internal::complex_iter_base_< any_face_handle<D>, - complex_bkd_iter_<D> > - { - public: - /// Type of associated face. - typedef any_face_handle<D> face; - - private: - typedef complex_bkd_iter_<D> self_; - typedef internal::complex_iter_base_< face, self_ > super_; - - public: - using super_::is_valid; - using super_::invalidate; - - public: - /// Construction and assignment. - /// \{ - complex_bkd_iter_(); - // FIXME: See comment in internal::complex_iter_base_'s default ctor - complex_bkd_iter_(complex<D>& c); - /// \} - - /// Manipulation. - /// \{ - /// Start an iteration. - void start(); - /// Go to the next point. - void next_(); - /// \} - - private: - using super_::face_; - }; - - - -# ifndef MLN_INCLUDE_ONLY - - /*-----------------------. - | complex_fwd_iter_<D>. | - `-----------------------*/ - - template <unsigned D> - inline - complex_fwd_iter_<D>::complex_fwd_iter_() - : super_() - { - } - - template <unsigned D> - inline - complex_fwd_iter_<D>::complex_fwd_iter_(complex<D>& c) - : super_(c) - { - set_cplx(c); - mln_postcondition(!is_valid()); - } - - template <unsigned D> - inline - void - complex_fwd_iter_<D>::start() - { - face_.set_n(0u); - face_.set_face_id(0u); - } - - template <unsigned D> - inline - void - complex_fwd_iter_<D>::next_() - { - if (is_valid()) - { - unsigned n = face_.n(); - unsigned face_id = face_.face_id(); - - if (face_id + 1 < face_.cplx().nfaces(n)) - /* FIXME: Provide accessor any_face_handle::face_id() returning - a mutable reference? This way, we could just write - - ++face_.face_id(); - - instead of the following. - - Or add {inc,add}_face_id() services. */ - face_.set_face_id(face_id + 1); - else - // Start to iterate on the faces of the next dimension if - // possible. - if (n <= D) - { - // FIXME: Same remark as above. - face_.set_n(n + 1); - face_.set_face_id(0u); - } - else - invalidate(); - } - } - - - /*-----------------------. - | complex_bkd_iter_<D>. | - `-----------------------*/ - - template <unsigned D> - inline - complex_bkd_iter_<D>::complex_bkd_iter_() - : super_() - { - } - - template <unsigned D> - inline - complex_bkd_iter_<D>::complex_bkd_iter_(complex<D>& c) - : super_(c) - { - set_cplx(c); - mln_postcondition(!is_valid()); - } - - template <unsigned D> - inline - void - complex_bkd_iter_<D>::start() - { - face_.set_n(D); - face_.set_face_id(face_.cplx().template nfaces<D>() - 1); - } - - template <unsigned D> - inline - void - complex_bkd_iter_<D>::next_() - { - if (is_valid()) - { - unsigned n = face_.n(); - unsigned face_id = face_.face_id(); - - if (face_id > 0) - /* FIXME: Provide accessor any_face_handle::face_id() returning - a mutable reference? This way, we could just write - - ++face_.face_id(); - - instead of the following. - - Or add {inc,add}_face_id() services. */ - face_.set_face_id(face_id - 1); - else - // Start to iterate on the faces of the previous dimension - // if it exists. - if (n > 0) - { - // FIXME: Same remark as above. - face_.set_n(n - 1); - face_.set_face_id(face_.cplx().nfaces(n - 1) - 1); - } - else - invalidate(); - } - } - -# endif // ! MLN_INCLUDE_ONLY - -} // end of mln - - -#endif // ! MLN_CORE_COMPLEX_ITER_HH diff --git a/milena/mln/core/face.hh b/milena/mln/core/face.hh deleted file mode 100644 index 4692d65..0000000 --- a/milena/mln/core/face.hh +++ /dev/null @@ -1,729 +0,0 @@ -// 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_FACE_HH -# define MLN_CORE_FACE_HH - -/// \file mln/core/face.hh -/// \brief Face of a complex. - -#include <limits> - -#include <vector> - -#include <mln/core/contract.hh> - -/* FIXME: Suggestions: - - - rename `face' as `face_data', and move it into complex.hh or its - own file; - - rename `face_handle' as `face', and move it to its own file; - - rename `any_face_handle' as `any_face', and move it to its own file. - - Anyway, whatever the decision, splitting `face', `face_handle' and - `any_face_handle' seems to be sound. - - (And what about `faces_set'? Should we move it to its own file as - well?) */ - -namespace mln -{ - - // Forward declarations (external). - template <unsigned D> class complex; - namespace internal - { - template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin; - template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin; - } - - // Forward declarations (internal). - template <unsigned N, unsigned D> class face_handle; - namespace internal - { - template <unsigned N, unsigned D> class lower_dim_faces_mixin; - template <unsigned N, unsigned D> class higher_dim_faces_mixin; - } - - - /*-------. - | Face. | - `-------*/ - - /// \p N-face of a \p D-complex. - template <unsigned N, unsigned D> class face; - - - // Specialization for the faces of highest dimension (\p D). - template <unsigned D> - class face<D, D> : public internal::lower_dim_faces_mixin<D, D> - { - }; - - // Specialization for the faces of intermediate dimension (greater - // than 0, lower than \p D). - template <unsigned N, unsigned D> - class face : public internal::lower_dim_faces_mixin<N, D>, - public internal::higher_dim_faces_mixin<N, D> - { - }; - - // Specialization for the faces of lowest dimension (0). - template <unsigned D> - class face<0u, D> : public internal::higher_dim_faces_mixin<0u, D> - { - }; - - // Specialization for the case of a 0-complex. - template <> - class face<0u, 0u> - { - }; - - - namespace internal - { - - /// Factored implementation of faces. - /// \{ - template <unsigned N, unsigned D> - class lower_dim_faces_mixin - { - public: - void connect_lower_dim_face (const face_handle<N - 1, D>& f); - private: - friend class mln::internal::lower_dim_faces_set_mixin<N, D>; - std::vector< face_handle<N - 1, D> > lower_dim_faces_; - }; - - template <unsigned N, unsigned D> - class higher_dim_faces_mixin - { - public: - void connect_higher_dim_face(const face_handle<N + 1, D>& f); - private: - friend class mln::internal::higher_dim_faces_set_mixin<N, D>; - std::vector< face_handle<N + 1, D> > higher_dim_faces_; - }; - /// \} - - } // end of namespace mln::internal - - - - /*--------------. - | Face handle. | - `--------------*/ - - // Face handle in a complex. - 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. - face_handle(complex<D>& complex, unsigned face_id); - - /// Copy and assignment. - /// \{ - face_handle(const face_handle<N, D>& rhs); - face_handle<N, D>& operator=(const face_handle<N, D>& rhs); - /// \} - - /// Is this handle valid? - bool is_valid() const; - /// Invalidate this handle. - void invalidate(); - - /// Accessors. - /// \{ - /// Return the complex the face belongs to. - complex<D>& cplx() const; - /// Return the id of the face. - // FIXME: Rename as `id'? - unsigned face_id() const; - - /// 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); - - /// Return the mln::face pointed by this handle. - face<N, D>& to_face() const; - /// \} - - private: - /// \brief The complex the face belongs to. - /// - /// A const face_handle can be used to modify a complex. - mutable complex<D>* cplx_; - /// \brief The id of the face. - // FIXME: Rename as `id_'? - unsigned face_id_; - }; - - - /// Create a handle for \p N-face of a \p D-complex. - template <unsigned N, unsigned D> - face_handle<N, D> - make_face_handle(const complex<D>& c, unsigned face_id); - - - /// Comparison of two instances of mln::face_handle. - /// \{ - /// \brief Is \a lhs equal to \a rhs? - /// - /// \pre Arguments \a lhs and \a rhs must belong to the same - /// mln::complex. - template <unsigned N, unsigned D> - bool - operator==(const face_handle<N, D>& lhs, const face_handle<N, D>& rhs); - - /// \brief Is \a lhs ``less'' than \a rhs? - /// - /// This comparison is required by algorithms sorting face handles. - /// - /// \pre Arguments \a lhs and \a rhs must belong to the same - /// mln::complex. - template <unsigned N, unsigned D> - bool - operator< (const face_handle<N, D>& lhs, const face_handle<N, D>& rhs); - /// \} - - - /*----------------------. - | Set of face handles. | - `----------------------*/ - - /// \brief Set of face handles of dimension \p N. - template <unsigned N, unsigned D> - class faces_set - { - public: - void add(const face_handle<N, D>& f); - - /// \brief Accessors. - /// - /// Return the set of handles. - /// \{ - const std::vector< face_handle<N, D> >& faces() const; - /// \} - - private: - friend class mln::complex<D>; - - // FIXME: Rename this as `handles_'? - std::vector< face_handle<N, D> > faces_; - }; - - - /// Construction helpers for mln::faces_set. - /// \{ - template <unsigned N, unsigned D> - faces_set<N, D> - operator+(const face_handle<N, D>& f1, const face_handle<N, D>& f2); - - template <unsigned N, unsigned D> - faces_set<N, D> - operator+(const faces_set<N, D>& fs, const face_handle<N, D>& f); - /// \} - - - /*----------------------. - | ``Any-face'' handle. | - `----------------------*/ - - // Face handle in a complex, where the dimension is dynamic. - 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. - any_face_handle(complex<D>& complex, unsigned n, unsigned face_id); - - /// Build a face handle from a face_handle. - template <unsigned N> - any_face_handle(const face_handle<N, D>& f); - - /// Copy and assignment. - /// \{ - any_face_handle(const any_face_handle<D>& rhs); - any_face_handle<D>& operator=(const any_face_handle<D>& rhs); - /// \} - - /// Is this handle valid? - bool is_valid() const; - /// Invalidate this handle. - void invalidate(); - - /// Accessors. - /// \{ - /// Return the complex the face belongs to. - complex<D>& cplx() const; - /// Return the dimension of the face. - // FIXME: Rename as `dim'? - unsigned n() const; - /// Return the id of the face. - // FIXME: Rename as `id'? - unsigned face_id() const; - - /// Set the complex the face belongs to. - void set_cplx(complex<D>& cplx); - /// Set the dimension of the face. - void set_n(unsigned n); - /// Set the id of the face. - void set_face_id(unsigned face_id); - - /// Return the mln::face pointed by this handle. - template <unsigned N> - face<N, D>& to_face() const; - /// \} - - private: - /// \brief The complex the face belongs to. - /// - /// A const any_face_handle can be used to modify a complex. - mutable complex<D>* cplx_; - /// The dimension of the face. - // FIXME: Rename as `dim_'? - unsigned n_; - /// \brief The id of the face. - // FIXME: Rename as `id_'? - unsigned face_id_; - }; - - - /// Comparison of two instances of mln::any_face_handle. - /// \{ - /// \brief Is \a lhs equal to \a rhs? - /// - /// \pre Arguments \a lhs and \a rhs must belong to the same - /// mln::complex. - template <unsigned D> - bool - operator==(const any_face_handle<D>& lhs, const any_face_handle<D>& rhs); - - /// \brief Is \a lhs ``less'' than \a rhs? - /// - /// This comparison is required by algorithms sorting face handles. - /// - /// \pre Arguments \a lhs and \a rhs must belong to the same - /// mln::complex. - /// \pre Arguments \a lhs and \a rhs must have the same dimension. - template <unsigned D> - bool - operator< (const any_face_handle<D>& lhs, const any_face_handle<D>& rhs); - /// \} - - - -# ifndef MLN_INCLUDE_ONLY - - /*--------. - | Faces. | - `--------*/ - - namespace internal - { - template <unsigned N, unsigned D> - inline - void - lower_dim_faces_mixin<N, D>::connect_lower_dim_face(const face_handle<N - 1, D>& f) - { - lower_dim_faces_.push_back(f); - } - - template <unsigned N, unsigned D> - inline - void - higher_dim_faces_mixin<N, D>::connect_higher_dim_face(const face_handle<N + 1, D>& f) - { - higher_dim_faces_.push_back(f); - } - - } // end of namespace mln::internal - - - /*--------------. - | Face handle. | - `--------------*/ - - template <unsigned N, unsigned D> - inline - face_handle<N, D>::face_handle() - : cplx_(0), face_id_(std::numeric_limits<unsigned>::max()) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - } - - template <unsigned N, unsigned D> - inline - face_handle<N, D>::face_handle(complex<D>& c, unsigned face_id) - : cplx_(&c), face_id_(face_id) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - } - - template <unsigned N, unsigned D> - inline - face_handle<N, D>::face_handle(const face_handle<N, D>& rhs) - : cplx_(rhs.cplx_), face_id_(rhs.face_id_) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - } - - template <unsigned N, unsigned D> - inline - face_handle<N, D>& - face_handle<N, D>::operator=(const face_handle<N, D>& rhs) - { - if (&rhs != this) - { - cplx_ = rhs.cplx_; - face_id_ = rhs.face_id_; - } - return *this; - } - - template <unsigned N, unsigned D> - inline - bool - face_handle<N, D>::is_valid() const - { - return cplx_ != 0 && face_id_ < cplx_->template nfaces<N>(); - } - - template <unsigned N, unsigned D> - inline - void - face_handle<N, D>::invalidate() - { - set_face_id(std::numeric_limits<unsigned>::max()); - } - - template <unsigned N, unsigned D> - inline - complex<D>& - face_handle<N, D>::cplx() const - { - mln_precondition(cplx_); - return *cplx_; - } - - template <unsigned N, unsigned D> - inline - unsigned - face_handle<N, D>::n() const - { - return N; - } - - template <unsigned N, unsigned D> - inline - unsigned - face_handle<N, D>::face_id() const - { - return face_id_; - } - - template <unsigned N, unsigned D> - inline - void - face_handle<N, D>::set_cplx(complex<D>& cplx) - { - cplx_ = &cplx; - } - - template <unsigned N, unsigned D> - inline - void - face_handle<N, D>::set_face_id(unsigned face_id) - { - face_id_ = face_id; - } - - template <unsigned N, unsigned D> - inline - face<N, D>& - face_handle<N, D>::to_face() const - { - mln_precondition(is_valid()); - return cplx_->template face_<N>(face_id_); - } - - - template <unsigned N, unsigned D> - inline - face_handle<N, D> - make_face_handle(const complex<D>& c, unsigned face_id) - { - return face_handle<N, D>(&c, face_id); - } - - template <unsigned N, unsigned D> - inline - bool - operator==(const face_handle<N, D>& lhs, const face_handle<N, D>& rhs) - { - // Ensure LHS and RHS belong to the same complex. - mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); - return lhs.face().id() == rhs.face().id(); - } - - template <unsigned N, unsigned D> - inline - bool - operator< (const face_handle<N, D>& lhs, const face_handle<N, D>& rhs) - { - // Ensure LHS and RHS belong to the same complex. - mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); - return lhs.face().id() < rhs.face().id(); - } - - - /*---------------. - | Set of faces. | - `---------------*/ - - template <unsigned N, unsigned D> - inline - void - faces_set<N, D>::add(const face_handle<N, D>& f) - { - // Check consistency. - if (!faces_.empty()) - mln_precondition(&faces_.front().cplx() == &f.cplx()); - faces_.push_back(f); - } - - template <unsigned N, unsigned D> - inline - const std::vector< face_handle<N, D> >& - faces_set<N, D>::faces() const - { - return faces_; - } - - - template <unsigned N, unsigned D> - inline - faces_set<N, D> - operator+(const face_handle<N, D>& f1, const face_handle<N, D>& f2) - { - faces_set<N, D> fs; - fs.add(f1); - fs.add(f2); - return fs; - } - - template <unsigned N, unsigned D> - inline - faces_set<N, D> - operator+(const faces_set<N, D>& fs, const face_handle<N, D>& f) - { - faces_set<N, D> fs2(fs); - fs2.add(f); - return fs2; - } - - - /*----------------------. - | ``Any-face'' handle. | - `----------------------*/ - - template <unsigned D> - inline - any_face_handle<D>::any_face_handle() - : cplx_(0), - n_(std::numeric_limits<unsigned>::max()), - face_id_(std::numeric_limits<unsigned>::max()) - { - } - - template <unsigned D> - inline - any_face_handle<D>::any_face_handle(complex<D>& c, unsigned n, - unsigned face_id) - : cplx_(&c), n_(n), face_id_(face_id) - { - // Ensure N is compatible with D. - mln_precondition(n <= D); - } - - template <unsigned D> - template <unsigned N> - inline - any_face_handle<D>::any_face_handle(const face_handle<N, D>& f) - : cplx_(&f.cplx()), n_(N), face_id_(f.face_id()) - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - - } - - template <unsigned D> - inline - any_face_handle<D>::any_face_handle(const any_face_handle<D>& rhs) - : cplx_(rhs.cplx_), n_(rhs.n_), face_id_(rhs.face_id_) - { - } - - template <unsigned D> - inline - any_face_handle<D>& - any_face_handle<D>::operator=(const any_face_handle<D>& rhs) - { - if (&rhs != this) - { - cplx_ = rhs.cplx_; - n_ = rhs.n_; - face_id_ = rhs.face_id_; - } - return *this; - } - - template <unsigned D> - inline - bool - any_face_handle<D>::is_valid() const - { - return cplx_ != 0 && n_ <= D && face_id_ < cplx_->nfaces(n_); - } - - template <unsigned D> - inline - void - any_face_handle<D>::invalidate() - { - set_n(std::numeric_limits<unsigned>::max()); - set_face_id(std::numeric_limits<unsigned>::max()); - } - - template <unsigned D> - inline - complex<D>& - any_face_handle<D>::cplx() const - { - mln_precondition(cplx_); - return *cplx_; - } - - template <unsigned D> - inline - unsigned - any_face_handle<D>::n() const - { - return n_; - } - - template <unsigned D> - inline - unsigned - any_face_handle<D>::face_id() const - { - return face_id_; - } - - template <unsigned D> - inline - void - any_face_handle<D>::set_cplx(complex<D>& cplx) - { - cplx_ = &cplx; - } - - template <unsigned D> - inline - void - any_face_handle<D>::set_n(unsigned n) - { - n_ = n; - } - - template <unsigned D> - inline - void - any_face_handle<D>::set_face_id(unsigned face_id) - { - face_id_ = face_id; - } - - template <unsigned D> - template <unsigned N> - inline - face<N, D>& - any_face_handle<D>::to_face() const - { - mln_precondition(n_ == N); - mln_precondition(is_valid()); - return cplx_->template face_<N>(face_id_); - } - - - template <unsigned D> - inline - bool - operator==(const any_face_handle<D>& lhs, const any_face_handle<D>& rhs) - { - // Ensure LHS and RHS belong to the same complex. - mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); - return - lhs.face().n() == rhs.face().n() && - lhs.face().id() == rhs.face().id(); - } - - template <unsigned D> - inline - bool - operator< (const any_face_handle<D>& lhs, const any_face_handle<D>& rhs) - { - // Ensure LHS and RHS belong to the same complex. - mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); - // Ensure LHS and RHS have the same dimension. - mln_precondition(lhs.face().n() == rhs.face().n()); - return lhs.face().id() < rhs.face().id(); - } - -# endif // ! MLN_INCLUDE_ONLY - -} // end of namespace mln - - -#endif // ! MLN_CORE_FACE_HH diff --git a/milena/mln/core/faces_iter.hh b/milena/mln/core/faces_iter.hh deleted file mode 100644 index 6194deb..0000000 --- a/milena/mln/core/faces_iter.hh +++ /dev/null @@ -1,247 +0,0 @@ -// 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 <mln/core/internal/complex_iter_base.hh> - -namespace mln -{ - - /*------------------------. - | 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::complex_iter_base_< face_handle<N, D>, - faces_fwd_iter_<N, D> > - { - public: - /// Type of associated face. - typedef face_handle<N, D> face; - - private: - typedef faces_fwd_iter_<N, D> self_; - typedef internal::complex_iter_base_< face, self_ > super_; - - public: - using super_::is_valid; - using super_::invalidate; - - public: - /// Construction and assignment. - /// \{ - faces_fwd_iter_(); - // FIXME: See comment in internal::complex_iter_base_'s default ctor - faces_fwd_iter_(complex<D>& c); - /// \} - - /// 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::complex_iter_base_< face_handle<N, D>, - faces_bkd_iter_<N, D> > - { - public: - /// Type of associated face. - typedef face_handle<N, D> face; - - private: - typedef faces_bkd_iter_<N, D> self_; - typedef internal::complex_iter_base_< face, self_ > super_; - - public: - using super_::is_valid; - using super_::invalidate; - - public: - /// Construction and assignment. - /// \{ - faces_bkd_iter_(); - // FIXME: See comment in internal::complex_iter_base_'s default ctor - faces_bkd_iter_(complex<D>& c); - /// \} - - /// Manipulation. - /// \{ - /// Start an iteration. - void start(); - /// Go to the next point. - void next_(); - /// \} - - private: - using super_::face_; - }; - - - -# ifndef MLN_INCLUDE_ONLY - - /*------------------------. - | faces_fwd_iter_<N, D>. | - `------------------------*/ - - template <unsigned N, unsigned D> - inline - faces_fwd_iter_<N, D>::faces_fwd_iter_() - : super_() - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - mln_postcondition(!is_valid()); - } - - 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(); - mln_postcondition(!is_valid()); - } - - 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>. | - `------------------------*/ - - template <unsigned N, unsigned D> - inline - faces_bkd_iter_<N, D>::faces_bkd_iter_() - : super_() - { - // Ensure N is compatible with D. - metal::bool_< N <= D >::check(); - mln_postcondition(!is_valid()); - } - - 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(); - mln_postcondition(!is_valid()); - } - - 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/internal/complex_iter_base.hh b/milena/mln/core/internal/complex_iter_base.hh deleted file mode 100644 index e2c747a..0000000 --- a/milena/mln/core/internal/complex_iter_base.hh +++ /dev/null @@ -1,202 +0,0 @@ -// 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/internal/complex_iter_base.hh -/// \brief Definition of an implementation (factoring) class for -/// iterators on mln::complex. - -# include <limits> - -# include <mln/metal/equal.hh> - -# include <mln/core/concept/iterator.hh> -# include <mln/core/complex.hh> - -namespace mln -{ - - namespace internal - { - /// \brief Factoring class for iterators on mln::complex. - /// - /// \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; - // FIXME: Maybe we could just get the dimension D of the face's - // complex, an define complex_type as mln::complex<D>? - 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); - /// \} - - /// Manipulation. - /// \{ - /// Change the target complex. - // FIXME: Same comment as the ctor above. - void set_cplx(complex_type& c); - - /// 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); - - - -# ifndef MLN_INCLUDE_ONLY - - 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 - void - complex_iter_base_<F, E>::set_cplx(complex_type& c) - { - face_.set_cplx(c); - // Invalidate face_. - invalidate(); - } - - 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 diff --git a/milena/mln/topo/complex.hh b/milena/mln/topo/complex.hh new file mode 100644 index 0000000..ae69dee --- /dev/null +++ b/milena/mln/topo/complex.hh @@ -0,0 +1,857 @@ +// 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_TOPO_COMPLEX_HH +# define MLN_TOPO_COMPLEX_HH + +/// \file mln/core/topo/complex.hh +/// \brief Structures for general complexes. +/// +/// A complex defines a topological space which can be used as a +/// support for an image (i.e., as site sets). + +# include <cstddef> + +# include <limits> +# include <iosfwd> + +# include <mln/metal/bool.hh> + +# include <mln/util/tracked_ptr.hh> + +# include <mln/topo/face.hh> + +# include <mln/topo/complex_iter.hh> +# include <mln/topo/faces_iter.hh> +# include <mln/topo/complex_faces_iter.hh> + + +namespace mln +{ + + namespace topo + { + + // Forward declarations. + namespace internal + { + template <unsigned D> + struct complex_data; + + template <unsigned N, unsigned D> + struct faces_set_mixin; + } + 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_; + + + /*----------. + | Complex. | + `----------*/ + + /// \brief General complex of dimension \p D. + template <unsigned D> + class complex + { + public: + /// Forward mln::Iterator type iterating on all faces. + typedef complex_fwd_iter_<D> fwd_citer; + /// 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. + /// \{ + /// Create a new \p D-complex. + complex(); + + /// \brief Add a 0-face to the complex. + face_handle<0u, D> add_face(); + + /// \brief Add a \p (N+1)-face to the complex (with \p N >= 0). + /// + /// \param adjacent_faces The (\p N-1)-faces adjacent to the new + /// \p N-face. + template <unsigned N> + face_handle<N + 1, D> add_face(const faces_set<N, D>& adjacent_faces); + /// \} + + /// \brief Static manipulators. + /// + /// These methods use statically-known input. + /// \{ + /// \brief Return the total number of faces, whatever their + /// dimension. + std::size_t nfaces() const; + + /// \brief Return the number of \p N-faces. + template <unsigned N> + std::size_t nfaces() const; + /// \} + + /// \brief Dynamic manipulators. + /// + /// These methods use input know as run time. + /// \{ + /// \brief Return the number of \a n-faces. + /// + /// Warning, this function has a complexity linear in term of N, + /// since each faces_set is checked (the present implementation + /// does not provide a direct access to faces_set through a + /// dynamic value of the dimension). + std::size_t nfaces(unsigned n) const; + /// \} + + /// Pretty-printing. + /// \{ + /// Print the complex. + void print(std::ostream& ostr) const; + /// Print the faces of dimension \p N. + template <unsigned N> + void print_faces(std::ostream& ostr) const; + /// \} + + private: + /// The actual data of the complex. + util::tracked_ptr< internal::complex_data<D> > data_; + + template <unsigned D_> + friend bool operator==(const complex<D_>& lhs, const complex<D_>& rhs); + + /// Accessors. + /// \{ + template <unsigned N, unsigned D_> friend class face_handle; + template <unsigned D_> friend class any_face_handle; + + template <unsigned N> + face<N, D>& face_(unsigned face_id); + + template <unsigned N> + const face<N, D>& face_(unsigned face_id) const; + /// \} + + /// Functional meta-manipulators. + /// \{ + /* FIXME: Use something more constraining than the STL's + UnaryFunction/BinaryFunction. Use Function or Function_v2v? + Or a new subclass of Function? */ + + /* FIXME: Replace F and ACCU by a Milena accumulator? */ + + /** \brief Apply a kind of static fold left operator to the + implicit list of faces_set using a functor \a f and a value \a + accu. + + Argument \a is called an "accumulator", but with a slightly + different meaning than mln:accu members. + + We might want to use TypeLists or something similar, is they + provide an explicit static fold left operator. */ + template <typename BinaryFunction, typename T> + T fold_left_(const BinaryFunction& f, const T& accu) const; + + /// \brief Apply a functor \a f to this list of \a n-faces. + template <typename UnaryFunction> + typename UnaryFunction::result_type + apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; + /// \} + + /// \brief connect two faces. + /// + /// \param f1 A face of dimension \p N + /// \param f2 A face of dimension \p N + 1 + /// + /// \pre \p N must be lower or equal to \p D. + template <unsigned N> + void connect_(const face_handle<N, D>& f1, + const face_handle<N + 1, D>& f2); + }; + + + /// Compare two complexes for equality. + template <unsigned D> + bool + operator==(const complex<D>& lhs, const complex<D>& rhs); + + + /// Pretty print a complex. + template <unsigned D> + std::ostream& + operator<<(std::ostream& ostr, const complex<D>& c); + + + /*---------------. + | Complex data. | + `---------------*/ + + namespace internal + { + // Forward declarations. + template <unsigned N, unsigned D> + struct faces_set_mixin; + + /// \brief Complex data. + template <unsigned D> + struct complex_data : faces_set_mixin<D, D> + { + // Data is contained in super classes. + }; + + } // end of namespace mln::topo::internal + + + /*---------------------. + | Faces of a complex. | + `---------------------*/ + + /// The sets of n-faces of a complex are recursively aggregated as + /// mixins. + namespace internal + { + + // Forward declarations. + template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin; + template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin; + + // -------------------------------------- // + // mln::topo::internal::faces_set_mixin. // + // -------------------------------------- // + + /// \brief Recursive mixins of set of faces. + /// \{ + template <unsigned N, unsigned D> struct faces_set_mixin; + + /// Faces of highest dimension (\p D). + template <unsigned D> + struct faces_set_mixin<D, D> : public faces_set_mixin<D - 1, D>, + public lower_dim_faces_set_mixin<D, D> + { + std::vector< face<D, D> > faces_; + + /// Pretty-printing. + /// \{ + /// Print the faces of dimension \p D. + void print(std::ostream& ostr) const; + void print_rec_asc(std::ostream& ostr) const; + /// \} + + /// Functional meta-manipulators. + /// \{ + /// \brief Fold left. + /// \see mln::complex<D>::fold_left_. + template <typename BinaryFunction, typename T> + T fold_left_(const BinaryFunction& f, const T& accu) const; + /// \brief Apply a functor \a f to the list of faces if \a n == \p D. + /// \see mln::complex<D>::apply_if_dim_matches_. + template <typename UnaryFunction> + typename UnaryFunction::result_type + apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; + /// \} + }; + + /// Faces of intermediate dimension (greater than 0, lower than \p D). + template <unsigned N, unsigned D> + struct faces_set_mixin : public faces_set_mixin<N - 1, D>, + public lower_dim_faces_set_mixin<N, D>, + public higher_dim_faces_set_mixin<N, D> + { + std::vector< face<N, D> > faces_; + + /// Pretty-printing. + /// \{ + /// Print the faces of dimension \p N. + void print(std::ostream& ostr) const; + /// Recursively print the faces of dimensions 0 to \p N + /// (in ascending dimension). + void print_rec_asc(std::ostream& ostr) const; + /// \} + + /// Functional meta-manipulators. + /// \{ + /// \brief Fold left. + /// \see mln::complex<D>::fold_left_. + template <typename BinaryFunction, typename T> + T fold_left_(const BinaryFunction& f, const T& accu) const; + /// \brief Apply a functor \a f to the list of faces if \a n == \p N. + /// \see mln::complex<D>::apply_if_dim_matches_. + template <typename UnaryFunction> + typename UnaryFunction::result_type + apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; + /// \} + }; + + /// Faces of lowest dimension (0). + template <unsigned D> + struct faces_set_mixin<0u, D> : public higher_dim_faces_set_mixin<0u, D> + { + std::vector< face<0u, D> > faces_; + + /// Pretty-printing. + /// \{ + /// Print the faces of dimension 0. + void print(std::ostream& ostr) const; + void print_rec_asc(std::ostream& ostr) const; + /// \} + + /// Functional meta-manipulators. + /// \{ + /// \brief Fold left. + /// \see mln::complex<D>::fold_left_. + template <typename BinaryFunction, typename T> + T fold_left_(const BinaryFunction& f, const T& accu) const; + /// \brief Apply a functor \a f to the list of faces if \a n == 0. + /// \see mln::complex<D>::apply_if_dim_matches_. + template <typename UnaryFunction> + typename UnaryFunction::result_type + apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; + /// \} + }; + + /// Faces of a 0-complex. + template <> + struct faces_set_mixin<0u, 0u> + { + std::vector< face<0u, 0u> > faces_; + + /// Pretty-printing. + /// \{ + /// Print the faces of dimension \p D. + void print(std::ostream& ostr) const; + void print_rec_asc(std::ostream& ostr) const; + /// \} + + /// Functional meta-manipulators. + /// \{ + /// \brief Fold left. + /// \see mln::complex<D>::fold_left_. + template <typename BinaryFunction, typename T> + T fold_left_(const BinaryFunction& f, const T& accu) const; + /// \brief Apply a functor \a f to the list of faces if \a n == 0. + /// \see mln::complex<D>::apply_if_dim_matches_. + template <typename UnaryFunction> + typename UnaryFunction::result_type + apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const; + /// \} + }; + /// \} + + + // ------------------------------------------------- // + // mln::topo::internal::lower_dim_faces_set_mixin. // + // mln::topo::internal::higher_dim_faces_set_mixin. // + // ------------------------------------------------- // + + /// Mixins of mixin mln::faces_set_mixin. + /// \{ + template <unsigned N, unsigned D> + struct lower_dim_faces_set_mixin + { + void print(std::ostream& ostr, const face<N, D>& f) const; + }; + + template <unsigned N, unsigned D> + struct higher_dim_faces_set_mixin + { + void print(std::ostream& ostr, const face<N, D>& f) const; + }; + /// \} + + } // end of namespace mln::topo::internal + + + +# ifndef MLN_INCLUDE_ONLY + + /*-----------------------. + | Complex construction. | + `-----------------------*/ + + template <unsigned D> + complex<D>::complex() + // Allocate data for this complex. + : data_(new internal::complex_data<D>()) + { + } + + template <unsigned D> + face_handle<0u, D> + complex<D>::add_face() + { + /* FIXME: This is not thread-proof (these two lines should + form an atomic section). */ + data_->internal::faces_set_mixin<0u, D>::faces_.push_back(face<0u, D>()); + unsigned id = nfaces<0u>() - 1; + + return face_handle<0u, D>(*this, id); + } + + template <unsigned D> + template <unsigned N> + face_handle<N + 1, D> + complex<D>::add_face(const faces_set<N, D>& adjacent_faces) + { + typedef typename std::vector< face_handle<N, D> >::const_iterator iter_t; + + // Ensure ADJACENT_FACES are already part of the complex. + if (!HAS_NDEBUG) + for (iter_t a = adjacent_faces.faces().begin(); + a != adjacent_faces.faces().end(); ++a) + { + mln_precondition(&a->cplx() == this); + mln_precondition(a->is_valid()); + } + + face<N + 1, D> f; + /* FIXME: This is not thread-proof (these two lines should + form an atomic section). */ + data_->internal::faces_set_mixin<N + 1, D>::faces_.push_back(f); + unsigned id = nfaces<N + 1>() - 1; + + face_handle<N + 1, D> fh(*this, id); + // Connect F and its ADJACENT_FACES. + for (iter_t a = adjacent_faces.faces().begin(); + a != adjacent_faces.faces().end(); ++a) + connect_(*a, fh); + return fh; + } + + + /*-------. + | Misc. | + `-------*/ + + namespace internal + { + + /// A binary meta-functor defined by: + /// + /// \code + /// add_size : x, c -> x + c.size() + /// \endcode + /// + /// \see mln::complex<D>::nfaces (static version). + /// \see mln::complex<D>::fold_left_. + struct add_size + { + template <typename T, typename Container> + T operator()(const T& x, const Container& c) const + { + return x + c.size(); + } + }; + + /// An unary meta-functor defined by: + /// + /// \code + /// add_size : c -> c.size() + /// \endcode + /// + /// \see mln::complex<D>::nfaces (dynamic version). + /// \see mln::complex<D>::apply_if_dim_matches_. + struct get_size + { + typedef std::size_t result_type; + + template <typename Container> + typename Container::size_type operator()(const Container& c) const + { + return c.size(); + } + }; + + } // end of namespace mln::topo::internal + + + /*----------------------. + | Static manipulators. | + `----------------------*/ + + template <unsigned D> + std::size_t + complex<D>::nfaces() const + { + return fold_left_(internal::add_size(), 0); + } + + template <unsigned D> + template <unsigned N> + std::size_t + complex<D>::nfaces() const + { + return data_->internal::faces_set_mixin<N, D>::faces_.size(); + } + + + /*-----------------------. + | Dynamic manipulators. | + `-----------------------*/ + + template <unsigned D> + std::size_t + complex<D>::nfaces(unsigned n) const + { + // Ensure N is compatible with D. + mln_precondition(n <= D); + return apply_if_dim_matches_(n, internal::get_size()); + } + + + /*-------------------. + | Internal methods. | + `-------------------*/ + + template <unsigned D> + template <unsigned N> + face<N, D>& + complex<D>::face_(unsigned face_id) + { + return data_->internal::faces_set_mixin<N, D>::faces_[face_id]; + } + + template <unsigned D> + template <unsigned N> + const face<N, D>& + complex<D>::face_(unsigned face_id) const + { + return data_->internal::faces_set_mixin<N, D>::faces_[face_id]; + } + + template <unsigned D> + template <unsigned N> + void + complex<D>::connect_(const face_handle<N, D>& f1, + const face_handle<N + 1, D>& f2) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + + f1.to_face().connect_higher_dim_face(f2); + f2.to_face().connect_lower_dim_face(f1); + } + + + /*-------------. + | Comparison. | + `-------------*/ + + template <unsigned D> + bool + operator==(const complex<D>& lhs, const complex<D>& rhs) + { + return lhs.data_.ptr_ == rhs.data_.ptr_; + } + + + /*------------------. + | Pretty-printing. | + `------------------*/ + + template <unsigned D> + std::ostream& + operator<<(std::ostream& ostr, const complex<D>& c) + { + c.print(ostr); + return ostr; + } + + template <unsigned D> + void + complex<D>::print(std::ostream& ostr) const + { + data_->internal::faces_set_mixin<D, D>::print_rec_asc(ostr); + } + + template <unsigned D> + template <unsigned N> + void + complex<D>::print_faces(std::ostream& ostr) const + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + + data_->internal::faces_set_mixin<N, D>::print(ostr); + } + + + namespace internal + { + + template <unsigned N, unsigned D> + void + faces_set_mixin<N, D>::print_rec_asc(std::ostream& ostr) const + { + faces_set_mixin<N - 1, D>::print_rec_asc(ostr); + print(ostr); + } + + template <unsigned D> + void + faces_set_mixin<0u, D>::print_rec_asc(std::ostream& ostr) const + { + print(ostr); + } + + template <unsigned D> + void + faces_set_mixin<D, D>::print_rec_asc(std::ostream& ostr) const + { + faces_set_mixin<D - 1, D>::print_rec_asc(ostr); + print(ostr); + } + + void + faces_set_mixin<0u, 0u>::print_rec_asc(std::ostream& ostr) const + { + print(ostr); + } + + + template <unsigned N, unsigned D> + void + faces_set_mixin<N, D>::print(std::ostream& ostr) const + { + ostr << "Faces of dimension " << N + << " and their ajacent faces of dimension " + << N - 1 << " and " + << N + 1 << std::endl; + for (unsigned f = 0; f < faces_.size(); ++f) + { + ostr << " " << f << ": dim " << N - 1 << ": { "; + lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); + ostr << "}, dim " << N + 1 << ": { "; + higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); + ostr << "}" << std::endl; + } + } + + template <unsigned D> + void + faces_set_mixin<0u, D>::print(std::ostream& ostr) const + { + const unsigned N = 0u; + ostr << "Faces of dimension " << N + << " and their ajacent faces of dimension " + << N + 1 << std::endl; + for (unsigned f = 0; f < faces_.size(); ++f) + { + ostr << " " << f << ": dim " << N + 1 << ": { "; + higher_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); + ostr << "}" << std::endl; + } + } + + template <unsigned D> + void + faces_set_mixin<D, D>::print(std::ostream& ostr) const + { + const unsigned N = D; + ostr << "Faces of dimension " << N + << " and their ajacent faces of dimension " + << N - 1 << std::endl; + for (unsigned f = 0; f < faces_.size(); ++f) + { + ostr << " " << f << ": dim " << N - 1 << ": { "; + lower_dim_faces_set_mixin<N, D>::print(ostr, faces_[f]); + ostr << "}" << std::endl; + } + } + + void + faces_set_mixin<0u, 0u>::print(std::ostream& ostr) const + { + const unsigned N = 0u; + ostr << "Faces of dimension " << N << std::endl; + for (unsigned f = 0; f < faces_.size(); ++f) + ostr << " " << f << std::endl; + } + + + template <unsigned N, unsigned D> + void + lower_dim_faces_set_mixin<N, D>::print(std::ostream& ostr, + const face<N, D>& f) const + { + for (typename std::vector< face_handle<N - 1, D> >::const_iterator l = + f.lower_dim_faces_.begin(); l != f.lower_dim_faces_.end(); ++l) + ostr << l->face_id() << " "; + } + + template <unsigned N, unsigned D> + void + higher_dim_faces_set_mixin<N, D>::print(std::ostream& ostr, + const face<N, D>& f) const + { + for (typename std::vector< face_handle<N + 1, D> >::const_iterator h = + f.higher_dim_faces_.begin(); h != f.higher_dim_faces_.end(); ++h) + ostr << h->face_id() << " "; + } + + } // end of namespace mln::topo::internal + + + /*-------------------------------. + | Functional meta-manipulators. | + `-------------------------------*/ + + /* ------------------------------- */ + /* ``Static Fold Left'' Operator. */ + /* ------------------------------- */ + + template <unsigned D> + template <typename BinaryFunction, typename T> + T + complex<D>::fold_left_(const BinaryFunction& f, const T& accu) const + { + return data_->internal::faces_set_mixin<D, D>::fold_left_(f, accu); + } + + namespace internal + { + + // FIXME: Try to factor. + + template <unsigned D> + template <typename BinaryFunction, typename T> + T + faces_set_mixin<D, D>::fold_left_(const BinaryFunction& f, + const T& accu) const + { + return faces_set_mixin<D - 1, D>::fold_left_(f, f(accu, faces_)); + } + + template <unsigned N, unsigned D> + template <typename BinaryFunction, typename T> + T + faces_set_mixin<N, D>::fold_left_(const BinaryFunction& f, + const T& accu) const + { + return faces_set_mixin<N - 1, D>::fold_left_(f, f(accu, faces_)); + } + + template <unsigned D> + template <typename BinaryFunction, typename T> + T + faces_set_mixin<0u, D>::fold_left_(const BinaryFunction& f, + const T& accu) const + { + return f(accu, faces_); + } + + template <typename BinaryFunction, typename T> + T + faces_set_mixin<0u, 0u>::fold_left_(const BinaryFunction& f, + const T& accu) const + { + return f(accu, faces_); + } + + } // end of namespace mln::topo::internal + + + /* ------------------------------------------------ */ + /* ``Static Apply-If-Dimension-Matches'' Operator. */ + /* ------------------------------------------------ */ + + template <unsigned D> + template <typename UnaryFunction> + typename UnaryFunction::result_type + complex<D>::apply_if_dim_matches_(unsigned n, const UnaryFunction& f) const + { + // Ensure N is compatible with D. + mln_precondition(n <= D); + return data_->internal::faces_set_mixin<D, D>::apply_if_dim_matches_(n, f); + } + + namespace internal + { + + // FIXME: Try to factor. + + template <unsigned D> + template <typename UnaryFunction> + typename UnaryFunction::result_type + faces_set_mixin<D, D>::apply_if_dim_matches_(unsigned n, + const UnaryFunction& f) const + { + // Ensure N and D are compatible. + mln_precondition(n <= D); + return n == D ? + f(faces_) : + faces_set_mixin<D - 1, D>::apply_if_dim_matches_(n, f); + } + + template <unsigned N, unsigned D> + template <typename UnaryFunction> + typename UnaryFunction::result_type + faces_set_mixin<N, D>::apply_if_dim_matches_(unsigned n, + const UnaryFunction& f) const + { + // Ensure N and D are compatible. + mln_precondition(n <= D); + return n == N ? + f(faces_) : + faces_set_mixin<N - 1, D>::apply_if_dim_matches_(n, f); + } + + template <unsigned D> + template <typename UnaryFunction> + typename UnaryFunction::result_type + faces_set_mixin<0u, D>::apply_if_dim_matches_(unsigned n, + const UnaryFunction& f) const + { + // If we reached this method, then N should be 0. + mln_precondition(n == 0); + return f(faces_); + } + + template <typename UnaryFunction> + typename UnaryFunction::result_type + faces_set_mixin<0u, 0u>::apply_if_dim_matches_(unsigned n, + const UnaryFunction& f) const + { + // If we reached this method, then N should be 0. + mln_precondition(n == 0); + return f(faces_); + } + + } // end of namespace mln::topo::internal + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::topo + +} // end of namespace mln + +#endif // ! MLN_TOPO_COMPLEX_HH diff --git a/milena/mln/topo/complex_faces_iter.hh b/milena/mln/topo/complex_faces_iter.hh new file mode 100644 index 0000000..05713da --- /dev/null +++ b/milena/mln/topo/complex_faces_iter.hh @@ -0,0 +1,266 @@ +// 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_TOPO_COMPLEX_FACES_ITER_HH +# define MLN_TOPO_COMPLEX_FACES_ITER_HH + +/// \file mln/topo/complex_faces_iter.hh +/// \brief Definition of forward and backward iterators on the n-faces +/// of a complex. + +# include <mln/topo/internal/complex_iter_base.hh> + +/* FIXME: Should we drop N from the signature of these iterators? + I.e., have N be dynamic? Or better: provide other iterators where + N is dynamic? */ + + +namespace mln +{ + + namespace topo + { + + /*--------------------------------------. + | topo::complex_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 complex_faces_fwd_iter_ + : public internal::complex_iter_base_< any_face_handle<D>, + complex_faces_fwd_iter_<N, D> > + { + public: + /// Type of associated face. + typedef any_face_handle<D> face; + + private: + typedef complex_faces_fwd_iter_<N, D> self_; + typedef internal::complex_iter_base_< face, self_ > super_; + + public: + using super_::is_valid; + using super_::invalidate; + + public: + /// Construction and assignment. + /// \{ + complex_faces_fwd_iter_(); + // FIXME: See comment in internal::complex_iter_base_'s default ctor + complex_faces_fwd_iter_(complex<D>& c); + /// \} + + /// Manipulation. + /// \{ + /// Test if the iterator is valid. + void start(); + /// Go to the next point. + void next_(); + /// \} + + private: + using super_::face_; + }; + + + /*--------------------------------------. + | topo::complex_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 complex_faces_bkd_iter_ + : public internal::complex_iter_base_< any_face_handle<D>, + complex_faces_bkd_iter_<N, D> > + { + public: + /// Type of associated face. + typedef any_face_handle<D> face; + + private: + typedef complex_faces_bkd_iter_<N, D> self_; + typedef internal::complex_iter_base_< face, self_ > super_; + + public: + using super_::is_valid; + using super_::invalidate; + + public: + /// Construction and assignment. + /// \{ + complex_faces_bkd_iter_(); + // FIXME: See comment in internal::complex_iter_base_'s default ctor + complex_faces_bkd_iter_(complex<D>& c); + /// \} + + /// Manipulation. + /// \{ + /// Start an iteration. + void start(); + /// Go to the next point. + void next_(); + /// \} + + private: + using super_::face_; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + /*--------------------------------------. + | topo::complex_faces_fwd_iter_<N, D>. | + `--------------------------------------*/ + + template <unsigned N, unsigned D> + inline + complex_faces_fwd_iter_<N, D>::complex_faces_fwd_iter_() + : super_() + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + face_.set_n(N); + mln_postcondition(!is_valid()); + } + + template <unsigned N, unsigned D> + inline + complex_faces_fwd_iter_<N, D>::complex_faces_fwd_iter_(complex<D>& c) + : super_(c) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + face_.set_n(N); + mln_postcondition(!is_valid()); + } + + template <unsigned N, unsigned D> + inline + void + complex_faces_fwd_iter_<N, D>::start() + { + face_.set_face_id(0u); + } + + template <unsigned N, unsigned D> + inline + void + complex_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 any_face_handle::face_id() + returning a mutable reference? This way, we could just + write + + ++face_.face_id(); + + instead of the following. + + Or add {inc,add}_face_id() services. */ + face_.set_face_id(face_id + 1); + else + invalidate(); + } + } + + + /*--------------------------------------. + | topo::complex_faces_bkd_iter_<N, D>. | + `--------------------------------------*/ + + template <unsigned N, unsigned D> + inline + complex_faces_bkd_iter_<N, D>::complex_faces_bkd_iter_() + : super_() + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + face_.set_n(N); + mln_postcondition(!is_valid()); + } + + template <unsigned N, unsigned D> + inline + complex_faces_bkd_iter_<N, D>::complex_faces_bkd_iter_(complex<D>& c) + : super_(c) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + face_.set_n(N); + mln_postcondition(!is_valid()); + } + + template <unsigned N, unsigned D> + inline + void + complex_faces_bkd_iter_<N, D>::start() + { + face_.set_face_id(face_.cplx().template nfaces<N>() - 1); + } + + template <unsigned N, unsigned D> + inline + void + complex_faces_bkd_iter_<N, D>::next_() + { + if (is_valid()) + { + unsigned face_id = face_.face_id(); + if (face_id > 0) + /* FIXME: Provide accessor any_face_handle::face_id() + returning a mutable reference? This way, we could just + write + + ++face_.face_id(); + + instead of the following. + + Or add {inc,add}_face_id() services. */ + face_.set_face_id(face_id - 1); + else + invalidate(); + } + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::topo + +} // end of namespace mln + +#endif // ! MLN_TOPO_COMPLEX_FACES_ITER_HH diff --git a/milena/mln/topo/complex_iter.hh b/milena/mln/topo/complex_iter.hh new file mode 100644 index 0000000..b30ca00 --- /dev/null +++ b/milena/mln/topo/complex_iter.hh @@ -0,0 +1,275 @@ +// 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_TOPO_COMPLEX_ITER_HH +# define MLN_TOPO_COMPLEX_ITER_HH + +/// \file mln/topo/complex_iter.hh +/// \brief Definition of forward and backward iterators on complexes. + +# include <mln/topo/internal/complex_iter_base.hh> + +// FIXME: Factor a bit more? (Using complex_iter_base_.) + + +namespace mln +{ + + namespace topo + { + + // Forward declaration. + template <unsigned D> class complex; + + + /*-----------------------------. + | topo::complex_fwd_iter_<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 internal::complex_iter_base_< any_face_handle<D>, + complex_fwd_iter_<D> > + { + public: + /// Type of associated face. + typedef any_face_handle<D> face; + + private: + typedef complex_fwd_iter_<D> self_; + typedef internal::complex_iter_base_< face, self_ > super_; + + public: + using super_::is_valid; + using super_::invalidate; + + public: + /// Construction and assignment. + /// \{ + complex_fwd_iter_(); + // FIXME: See comment in internal::complex_iter_base_'s default ctor + complex_fwd_iter_(complex<D>& c); + /// \} + + /// Manipulation. + /// \{ + /// Test if the iterator is valid. + void start(); + /// Go to the next point. + void next_(); + /// \} + + private: + using super_::face_; + }; + + + /*-----------------------------. + | topo::complex_bkd_iter_<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 internal::complex_iter_base_< any_face_handle<D>, + complex_bkd_iter_<D> > + { + public: + /// Type of associated face. + typedef any_face_handle<D> face; + + private: + typedef complex_bkd_iter_<D> self_; + typedef internal::complex_iter_base_< face, self_ > super_; + + public: + using super_::is_valid; + using super_::invalidate; + + public: + /// Construction and assignment. + /// \{ + complex_bkd_iter_(); + // FIXME: See comment in internal::complex_iter_base_'s default ctor + complex_bkd_iter_(complex<D>& c); + /// \} + + /// Manipulation. + /// \{ + /// Start an iteration. + void start(); + /// Go to the next point. + void next_(); + /// \} + + private: + using super_::face_; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + /*-----------------------------. + | topo::complex_fwd_iter_<D>. | + `-----------------------------*/ + + template <unsigned D> + inline + complex_fwd_iter_<D>::complex_fwd_iter_() + : super_() + { + } + + template <unsigned D> + inline + complex_fwd_iter_<D>::complex_fwd_iter_(complex<D>& c) + : super_(c) + { + set_cplx(c); + mln_postcondition(!is_valid()); + } + + template <unsigned D> + inline + void + complex_fwd_iter_<D>::start() + { + face_.set_n(0u); + face_.set_face_id(0u); + } + + template <unsigned D> + inline + void + complex_fwd_iter_<D>::next_() + { + if (is_valid()) + { + unsigned n = face_.n(); + unsigned face_id = face_.face_id(); + + if (face_id + 1 < face_.cplx().nfaces(n)) + /* FIXME: Provide accessor any_face_handle::face_id() returning + a mutable reference? This way, we could just write + + ++face_.face_id(); + + instead of the following. + + Or add {inc,add}_face_id() services. */ + face_.set_face_id(face_id + 1); + else + // Start to iterate on the faces of the next dimension if + // possible. + if (n <= D) + { + // FIXME: Same remark as above. + face_.set_n(n + 1); + face_.set_face_id(0u); + } + else + invalidate(); + } + } + + + /*-----------------------------. + | topo::complex_bkd_iter_<D>. | + `-----------------------------*/ + + template <unsigned D> + inline + complex_bkd_iter_<D>::complex_bkd_iter_() + : super_() + { + } + + template <unsigned D> + inline + complex_bkd_iter_<D>::complex_bkd_iter_(complex<D>& c) + : super_(c) + { + set_cplx(c); + mln_postcondition(!is_valid()); + } + + template <unsigned D> + inline + void + complex_bkd_iter_<D>::start() + { + face_.set_n(D); + face_.set_face_id(face_.cplx().template nfaces<D>() - 1); + } + + template <unsigned D> + inline + void + complex_bkd_iter_<D>::next_() + { + if (is_valid()) + { + unsigned n = face_.n(); + unsigned face_id = face_.face_id(); + + if (face_id > 0) + /* FIXME: Provide accessor any_face_handle::face_id() returning + a mutable reference? This way, we could just write + + ++face_.face_id(); + + instead of the following. + + Or add {inc,add}_face_id() services. */ + face_.set_face_id(face_id - 1); + else + // Start to iterate on the faces of the previous dimension + // if it exists. + if (n > 0) + { + // FIXME: Same remark as above. + face_.set_n(n - 1); + face_.set_face_id(face_.cplx().nfaces(n - 1) - 1); + } + else + invalidate(); + } + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::topo + +} // end of namespace mln + +#endif // ! MLN_TOPO_COMPLEX_ITER_HH diff --git a/milena/mln/topo/face.hh b/milena/mln/topo/face.hh new file mode 100644 index 0000000..11f22b2 --- /dev/null +++ b/milena/mln/topo/face.hh @@ -0,0 +1,733 @@ +// 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_TOPO_FACE_HH +# define MLN_TOPO_FACE_HH + +/// \file mln/topo/face.hh +/// \brief Face of a complex. + +#include <limits> + +#include <vector> + +#include <mln/core/contract.hh> + +/* FIXME: Suggestions: + + - rename `face' as `face_data', and move it into complex.hh or its + own file; + - rename `face_handle' as `face', and move it to its own file; + - rename `any_face_handle' as `any_face', and move it to its own file. + + Anyway, whatever the decision, splitting `face', `face_handle' and + `any_face_handle' seems to be sound. + + (And what about `faces_set'? Should we move it to its own file as + well?) */ + +namespace mln +{ + + namespace topo + { + + // Forward declarations (external). + template <unsigned D> class complex; + namespace internal + { + template <unsigned N, unsigned D> struct lower_dim_faces_set_mixin; + template <unsigned N, unsigned D> struct higher_dim_faces_set_mixin; + } + + // Forward declarations (internal). + template <unsigned N, unsigned D> class face_handle; + namespace internal + { + template <unsigned N, unsigned D> class lower_dim_faces_mixin; + template <unsigned N, unsigned D> class higher_dim_faces_mixin; + } + + + /*-------. + | Face. | + `-------*/ + + /// \p N-face of a \p D-complex. + template <unsigned N, unsigned D> class face; + + + // Specialization for the faces of highest dimension (\p D). + template <unsigned D> + class face<D, D> : public internal::lower_dim_faces_mixin<D, D> + { + }; + + // Specialization for the faces of intermediate dimension (greater + // than 0, lower than \p D). + template <unsigned N, unsigned D> + class face : public internal::lower_dim_faces_mixin<N, D>, + public internal::higher_dim_faces_mixin<N, D> + { + }; + + // Specialization for the faces of lowest dimension (0). + template <unsigned D> + class face<0u, D> : public internal::higher_dim_faces_mixin<0u, D> + { + }; + + // Specialization for the case of a 0-complex. + template <> + class face<0u, 0u> + { + }; + + + namespace internal + { + + /// Factored implementation of faces. + /// \{ + template <unsigned N, unsigned D> + class lower_dim_faces_mixin + { + public: + void connect_lower_dim_face (const face_handle<N - 1, D>& f); + private: + friend class mln::topo::internal::lower_dim_faces_set_mixin<N, D>; + std::vector< face_handle<N - 1, D> > lower_dim_faces_; + }; + + template <unsigned N, unsigned D> + class higher_dim_faces_mixin + { + public: + void connect_higher_dim_face(const face_handle<N + 1, D>& f); + private: + friend class mln::topo::internal::higher_dim_faces_set_mixin<N, D>; + std::vector< face_handle<N + 1, D> > higher_dim_faces_; + }; + /// \} + + } // end of namespace mln::topo::internal + + + + /*--------------. + | Face handle. | + `--------------*/ + + // Face handle in a complex. + 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. + face_handle(complex<D>& complex, unsigned face_id); + + /// Copy and assignment. + /// \{ + face_handle(const face_handle<N, D>& rhs); + face_handle<N, D>& operator=(const face_handle<N, D>& rhs); + /// \} + + /// Is this handle valid? + bool is_valid() const; + /// Invalidate this handle. + void invalidate(); + + /// Accessors. + /// \{ + /// Return the complex the face belongs to. + complex<D>& cplx() const; + /// Return the id of the face. + // FIXME: Rename as `id'? + unsigned face_id() const; + + /// 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); + + /// Return the mln::face pointed by this handle. + face<N, D>& to_face() const; + /// \} + + private: + /// \brief The complex the face belongs to. + /// + /// A const face_handle can be used to modify a complex. + mutable complex<D>* cplx_; + /// \brief The id of the face. + // FIXME: Rename as `id_'? + unsigned face_id_; + }; + + + /// Create a handle for \p N-face of a \p D-complex. + template <unsigned N, unsigned D> + face_handle<N, D> + make_face_handle(const complex<D>& c, unsigned face_id); + + + /// Comparison of two instances of mln::face_handle. + /// \{ + /// \brief Is \a lhs equal to \a rhs? + /// + /// \pre Arguments \a lhs and \a rhs must belong to the same + /// mln::complex. + template <unsigned N, unsigned D> + bool + operator==(const face_handle<N, D>& lhs, const face_handle<N, D>& rhs); + + /// \brief Is \a lhs ``less'' than \a rhs? + /// + /// This comparison is required by algorithms sorting face handles. + /// + /// \pre Arguments \a lhs and \a rhs must belong to the same + /// mln::complex. + template <unsigned N, unsigned D> + bool + operator< (const face_handle<N, D>& lhs, const face_handle<N, D>& rhs); + /// \} + + + /*----------------------. + | Set of face handles. | + `----------------------*/ + + /// \brief Set of face handles of dimension \p N. + template <unsigned N, unsigned D> + class faces_set + { + public: + void add(const face_handle<N, D>& f); + + /// \brief Accessors. + /// + /// Return the set of handles. + /// \{ + const std::vector< face_handle<N, D> >& faces() const; + /// \} + + private: + friend class complex<D>; + + // FIXME: Rename this as `handles_'? + std::vector< face_handle<N, D> > faces_; + }; + + + /// Construction helpers for mln::faces_set. + /// \{ + template <unsigned N, unsigned D> + faces_set<N, D> + operator+(const face_handle<N, D>& f1, const face_handle<N, D>& f2); + + template <unsigned N, unsigned D> + faces_set<N, D> + operator+(const faces_set<N, D>& fs, const face_handle<N, D>& f); + /// \} + + + /*----------------------. + | ``Any-face'' handle. | + `----------------------*/ + + // Face handle in a complex, where the dimension is dynamic. + 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. + any_face_handle(complex<D>& complex, unsigned n, unsigned face_id); + + /// Build a face handle from a face_handle. + template <unsigned N> + any_face_handle(const face_handle<N, D>& f); + + /// Copy and assignment. + /// \{ + any_face_handle(const any_face_handle<D>& rhs); + any_face_handle<D>& operator=(const any_face_handle<D>& rhs); + /// \} + + /// Is this handle valid? + bool is_valid() const; + /// Invalidate this handle. + void invalidate(); + + /// Accessors. + /// \{ + /// Return the complex the face belongs to. + complex<D>& cplx() const; + /// Return the dimension of the face. + // FIXME: Rename as `dim'? + unsigned n() const; + /// Return the id of the face. + // FIXME: Rename as `id'? + unsigned face_id() const; + + /// Set the complex the face belongs to. + void set_cplx(complex<D>& cplx); + /// Set the dimension of the face. + void set_n(unsigned n); + /// Set the id of the face. + void set_face_id(unsigned face_id); + + /// Return the mln::face pointed by this handle. + template <unsigned N> + face<N, D>& to_face() const; + /// \} + + private: + /// \brief The complex the face belongs to. + /// + /// A const any_face_handle can be used to modify a complex. + mutable complex<D>* cplx_; + /// The dimension of the face. + // FIXME: Rename as `dim_'? + unsigned n_; + /// \brief The id of the face. + // FIXME: Rename as `id_'? + unsigned face_id_; + }; + + + /// Comparison of two instances of mln::any_face_handle. + /// \{ + /// \brief Is \a lhs equal to \a rhs? + /// + /// \pre Arguments \a lhs and \a rhs must belong to the same + /// mln::complex. + template <unsigned D> + bool + operator==(const any_face_handle<D>& lhs, const any_face_handle<D>& rhs); + + /// \brief Is \a lhs ``less'' than \a rhs? + /// + /// This comparison is required by algorithms sorting face handles. + /// + /// \pre Arguments \a lhs and \a rhs must belong to the same + /// mln::complex. + /// \pre Arguments \a lhs and \a rhs must have the same dimension. + template <unsigned D> + bool + operator< (const any_face_handle<D>& lhs, const any_face_handle<D>& rhs); + /// \} + + + +# ifndef MLN_INCLUDE_ONLY + + /*--------. + | Faces. | + `--------*/ + + namespace internal + { + template <unsigned N, unsigned D> + inline + void + lower_dim_faces_mixin<N, D>::connect_lower_dim_face(const face_handle<N - 1, D>& f) + { + lower_dim_faces_.push_back(f); + } + + template <unsigned N, unsigned D> + inline + void + higher_dim_faces_mixin<N, D>::connect_higher_dim_face(const face_handle<N + 1, D>& f) + { + higher_dim_faces_.push_back(f); + } + + } // end of namespace mln::topo::internal + + + /*--------------. + | Face handle. | + `--------------*/ + + template <unsigned N, unsigned D> + inline + face_handle<N, D>::face_handle() + : cplx_(0), face_id_(std::numeric_limits<unsigned>::max()) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + } + + template <unsigned N, unsigned D> + inline + face_handle<N, D>::face_handle(complex<D>& c, unsigned face_id) + : cplx_(&c), face_id_(face_id) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + } + + template <unsigned N, unsigned D> + inline + face_handle<N, D>::face_handle(const face_handle<N, D>& rhs) + : cplx_(rhs.cplx_), face_id_(rhs.face_id_) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + } + + template <unsigned N, unsigned D> + inline + face_handle<N, D>& + face_handle<N, D>::operator=(const face_handle<N, D>& rhs) + { + if (&rhs != this) + { + cplx_ = rhs.cplx_; + face_id_ = rhs.face_id_; + } + return *this; + } + + template <unsigned N, unsigned D> + inline + bool + face_handle<N, D>::is_valid() const + { + return cplx_ != 0 && face_id_ < cplx_->template nfaces<N>(); + } + + template <unsigned N, unsigned D> + inline + void + face_handle<N, D>::invalidate() + { + set_face_id(std::numeric_limits<unsigned>::max()); + } + + template <unsigned N, unsigned D> + inline + complex<D>& + face_handle<N, D>::cplx() const + { + mln_precondition(cplx_); + return *cplx_; + } + + template <unsigned N, unsigned D> + inline + unsigned + face_handle<N, D>::n() const + { + return N; + } + + template <unsigned N, unsigned D> + inline + unsigned + face_handle<N, D>::face_id() const + { + return face_id_; + } + + template <unsigned N, unsigned D> + inline + void + face_handle<N, D>::set_cplx(complex<D>& cplx) + { + cplx_ = &cplx; + } + + template <unsigned N, unsigned D> + inline + void + face_handle<N, D>::set_face_id(unsigned face_id) + { + face_id_ = face_id; + } + + template <unsigned N, unsigned D> + inline + face<N, D>& + face_handle<N, D>::to_face() const + { + mln_precondition(is_valid()); + return cplx_->template face_<N>(face_id_); + } + + + template <unsigned N, unsigned D> + inline + face_handle<N, D> + make_face_handle(const complex<D>& c, unsigned face_id) + { + return face_handle<N, D>(&c, face_id); + } + + template <unsigned N, unsigned D> + inline + bool + operator==(const face_handle<N, D>& lhs, const face_handle<N, D>& rhs) + { + // Ensure LHS and RHS belong to the same complex. + mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); + return lhs.face().id() == rhs.face().id(); + } + + template <unsigned N, unsigned D> + inline + bool + operator< (const face_handle<N, D>& lhs, const face_handle<N, D>& rhs) + { + // Ensure LHS and RHS belong to the same complex. + mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); + return lhs.face().id() < rhs.face().id(); + } + + + /*---------------. + | Set of faces. | + `---------------*/ + + template <unsigned N, unsigned D> + inline + void + faces_set<N, D>::add(const face_handle<N, D>& f) + { + // Check consistency. + if (!faces_.empty()) + mln_precondition(&faces_.front().cplx() == &f.cplx()); + faces_.push_back(f); + } + + template <unsigned N, unsigned D> + inline + const std::vector< face_handle<N, D> >& + faces_set<N, D>::faces() const + { + return faces_; + } + + + template <unsigned N, unsigned D> + inline + faces_set<N, D> + operator+(const face_handle<N, D>& f1, const face_handle<N, D>& f2) + { + faces_set<N, D> fs; + fs.add(f1); + fs.add(f2); + return fs; + } + + template <unsigned N, unsigned D> + inline + faces_set<N, D> + operator+(const faces_set<N, D>& fs, const face_handle<N, D>& f) + { + faces_set<N, D> fs2(fs); + fs2.add(f); + return fs2; + } + + + /*----------------------. + | ``Any-face'' handle. | + `----------------------*/ + + template <unsigned D> + inline + any_face_handle<D>::any_face_handle() + : cplx_(0), + n_(std::numeric_limits<unsigned>::max()), + face_id_(std::numeric_limits<unsigned>::max()) + { + } + + template <unsigned D> + inline + any_face_handle<D>::any_face_handle(complex<D>& c, unsigned n, + unsigned face_id) + : cplx_(&c), n_(n), face_id_(face_id) + { + // Ensure N is compatible with D. + mln_precondition(n <= D); + } + + template <unsigned D> + template <unsigned N> + inline + any_face_handle<D>::any_face_handle(const face_handle<N, D>& f) + : cplx_(&f.cplx()), n_(N), face_id_(f.face_id()) + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + + } + + template <unsigned D> + inline + any_face_handle<D>::any_face_handle(const any_face_handle<D>& rhs) + : cplx_(rhs.cplx_), n_(rhs.n_), face_id_(rhs.face_id_) + { + } + + template <unsigned D> + inline + any_face_handle<D>& + any_face_handle<D>::operator=(const any_face_handle<D>& rhs) + { + if (&rhs != this) + { + cplx_ = rhs.cplx_; + n_ = rhs.n_; + face_id_ = rhs.face_id_; + } + return *this; + } + + template <unsigned D> + inline + bool + any_face_handle<D>::is_valid() const + { + return cplx_ != 0 && n_ <= D && face_id_ < cplx_->nfaces(n_); + } + + template <unsigned D> + inline + void + any_face_handle<D>::invalidate() + { + set_n(std::numeric_limits<unsigned>::max()); + set_face_id(std::numeric_limits<unsigned>::max()); + } + + template <unsigned D> + inline + complex<D>& + any_face_handle<D>::cplx() const + { + mln_precondition(cplx_); + return *cplx_; + } + + template <unsigned D> + inline + unsigned + any_face_handle<D>::n() const + { + return n_; + } + + template <unsigned D> + inline + unsigned + any_face_handle<D>::face_id() const + { + return face_id_; + } + + template <unsigned D> + inline + void + any_face_handle<D>::set_cplx(complex<D>& cplx) + { + cplx_ = &cplx; + } + + template <unsigned D> + inline + void + any_face_handle<D>::set_n(unsigned n) + { + n_ = n; + } + + template <unsigned D> + inline + void + any_face_handle<D>::set_face_id(unsigned face_id) + { + face_id_ = face_id; + } + + template <unsigned D> + template <unsigned N> + inline + face<N, D>& + any_face_handle<D>::to_face() const + { + mln_precondition(n_ == N); + mln_precondition(is_valid()); + return cplx_->template face_<N>(face_id_); + } + + + template <unsigned D> + inline + bool + operator==(const any_face_handle<D>& lhs, const any_face_handle<D>& rhs) + { + // Ensure LHS and RHS belong to the same complex. + mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); + return + lhs.face().n() == rhs.face().n() && + lhs.face().id() == rhs.face().id(); + } + + template <unsigned D> + inline + bool + operator< (const any_face_handle<D>& lhs, const any_face_handle<D>& rhs) + { + // Ensure LHS and RHS belong to the same complex. + mln_precondition(&lhs.face.cplx() == &rhs.face.cplx()); + // Ensure LHS and RHS have the same dimension. + mln_precondition(lhs.face().n() == rhs.face().n()); + return lhs.face().id() < rhs.face().id(); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::topo + +} // end of namespace mln + +#endif // ! MLN_TOPO_FACE_HH diff --git a/milena/mln/topo/faces_iter.hh b/milena/mln/topo/faces_iter.hh new file mode 100644 index 0000000..8f444c7 --- /dev/null +++ b/milena/mln/topo/faces_iter.hh @@ -0,0 +1,251 @@ +// 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_TOPO_FACES_ITER_HH +# define MLN_TOPO_FACES_ITER_HH + +/// \file mln/topo/faces_iter.hh +/// \brief Definition of forward and backward iterators on the n-faces +/// of a complex. + +# include <mln/topo/internal/complex_iter_base.hh> + +namespace mln +{ + + namespace topo + { + + /*------------------------------. + | topo::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::complex_iter_base_< face_handle<N, D>, + faces_fwd_iter_<N, D> > + { + public: + /// Type of associated face. + typedef face_handle<N, D> face; + + private: + typedef faces_fwd_iter_<N, D> self_; + typedef internal::complex_iter_base_< face, self_ > super_; + + public: + using super_::is_valid; + using super_::invalidate; + + public: + /// Construction and assignment. + /// \{ + faces_fwd_iter_(); + // FIXME: See comment in internal::complex_iter_base_'s default ctor + faces_fwd_iter_(complex<D>& c); + /// \} + + /// Manipulation. + /// \{ + /// Test if the iterator is valid. + void start(); + /// Go to the next point. + void next_(); + /// \} + + private: + using super_::face_; + }; + + + /*------------------------------. + | topo::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::complex_iter_base_< face_handle<N, D>, + faces_bkd_iter_<N, D> > + { + public: + /// Type of associated face. + typedef face_handle<N, D> face; + + private: + typedef faces_bkd_iter_<N, D> self_; + typedef internal::complex_iter_base_< face, self_ > super_; + + public: + using super_::is_valid; + using super_::invalidate; + + public: + /// Construction and assignment. + /// \{ + faces_bkd_iter_(); + // FIXME: See comment in internal::complex_iter_base_'s default ctor + faces_bkd_iter_(complex<D>& c); + /// \} + + /// Manipulation. + /// \{ + /// Start an iteration. + void start(); + /// Go to the next point. + void next_(); + /// \} + + private: + using super_::face_; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + /*------------------------------. + | topo::faces_fwd_iter_<N, D>. | + `------------------------------*/ + + template <unsigned N, unsigned D> + inline + faces_fwd_iter_<N, D>::faces_fwd_iter_() + : super_() + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + mln_postcondition(!is_valid()); + } + + 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(); + mln_postcondition(!is_valid()); + } + + 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(); + } + } + + + /*------------------------------. + | topo::faces_bkd_iter_<N, D>. | + `------------------------------*/ + + template <unsigned N, unsigned D> + inline + faces_bkd_iter_<N, D>::faces_bkd_iter_() + : super_() + { + // Ensure N is compatible with D. + metal::bool_< N <= D >::check(); + mln_postcondition(!is_valid()); + } + + 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(); + mln_postcondition(!is_valid()); + } + + 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 namespace mln::topo + +} // end of namespace mln + +#endif // ! MLN_TOPO_FACES_ITER_HH diff --git a/milena/mln/topo/internal/complex_iter_base.hh b/milena/mln/topo/internal/complex_iter_base.hh new file mode 100644 index 0000000..d371372 --- /dev/null +++ b/milena/mln/topo/internal/complex_iter_base.hh @@ -0,0 +1,208 @@ +// 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_TOPO_INTERNAL_COMPLEX_ITER_BASE_HH +# define MLN_TOPO_INTERNAL_COMPLEX_ITER_BASE_HH + +/// \file mln/topo/internal/complex_iter_base.hh +/// \brief Definition of an implementation (factoring) class for +/// iterators on mln::complex. + +# include <limits> + +# include <mln/metal/equal.hh> + +# include <mln/core/concept/iterator.hh> +# include <mln/topo/complex.hh> + + +namespace mln +{ + + namespace topo + { + + namespace internal + { + /// \brief Factoring class for iterators on mln::complex. + /// + /// \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; + // FIXME: Maybe we could just get the dimension D of the face's + // complex, an define complex_type as mln::complex<D>? + 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); + /// \} + + /// Manipulation. + /// \{ + /// Change the target complex. + // FIXME: Same comment as the ctor above. + void set_cplx(complex_type& c); + + /// 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); + + + +# ifndef MLN_INCLUDE_ONLY + + 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 + void + complex_iter_base_<F, E>::set_cplx(complex_type& c) + { + face_.set_cplx(c); + // Invalidate face_. + invalidate(); + } + + 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() << ')'; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::topo::internal + + } // end of namespace mln::topo + +} // end of namespace mln + +#endif // ! MLN_TOPO_INTERNAL_COMPLEX_ITER_BASE_HH diff --git a/milena/tests/Makefile.am b/milena/tests/Makefile.am index a26dd92..a6ec1dc 100644 --- a/milena/tests/Makefile.am +++ b/milena/tests/Makefile.am @@ -35,6 +35,7 @@ SUBDIRS = \ subsampling \ tag \ test \ + topo \ trace \ trait \ util \ diff --git a/milena/tests/core/other/Makefile.am b/milena/tests/core/other/Makefile.am index 4ecef66..f0e5fdf 100644 --- a/milena/tests/core/other/Makefile.am +++ b/milena/tests/core/other/Makefile.am @@ -7,7 +7,6 @@ check_PROGRAMS = \ category \ clock_neighb2d \ clock_test \ - complex \ dpoints_pixter \ graph_elt_neighborhood \ graph_elt_window \ @@ -27,7 +26,6 @@ box_runstart_piter_SOURCES = box_runstart_piter.cc category_SOURCES = category.cc clock_neighb2d_SOURCES = clock_neighb2d.cc clock_test_SOURCES = clock_test.cc -complex_SOURCES = complex.cc dpoints_pixter_SOURCES = dpoints_pixter.cc graph_elt_neighborhood_SOURCES = graph_elt_neighborhood.cc graph_elt_window_SOURCES = graph_elt_window.cc diff --git a/milena/tests/topo/Makefile.am b/milena/tests/topo/Makefile.am new file mode 100644 index 0000000..d6258d8 --- /dev/null +++ b/milena/tests/topo/Makefile.am @@ -0,0 +1,10 @@ +## Process this file through Automake to create Makefile.in -*- Makefile -*- + +include $(top_srcdir)/milena/tests/tests.mk + +check_PROGRAMS = \ + complex + +complex_SOURCES = complex.cc + +TESTS = $(check_PROGRAMS) diff --git a/milena/tests/core/other/complex.cc b/milena/tests/topo/complex.cc similarity index 79% rename from milena/tests/core/other/complex.cc rename to milena/tests/topo/complex.cc index a131f63..08be130 100644 --- a/milena/tests/core/other/complex.cc +++ b/milena/tests/topo/complex.cc @@ -25,19 +25,19 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/// \file tests/core/other/complex.cc +/// \file tests/topo/complex.cc /// \brief Test of mln::complex. #include <iostream> -#include <mln/core/complex.hh> +#include <mln/topo/complex.hh> using namespace mln; // Forward declaration. -template <unsigned N, unsigned D> void test_faces_iter(complex<D>& c); -template <unsigned N, unsigned D> void test_complex_faces_iter(complex<D>& c); +template <unsigned N, unsigned D> void test_faces_iter(topo::complex<D>& c); +template <unsigned N, unsigned D> void test_complex_faces_iter(topo::complex<D>& c); int main() @@ -66,24 +66,24 @@ int main() | Complex construction. | `-----------------------*/ - complex<D> c; + topo::complex<D> c; // 0-faces (points). - face_handle<0, D> v0 = c.add_face(); - face_handle<0, D> v1 = c.add_face(); - face_handle<0, D> v2 = c.add_face(); - face_handle<0, D> v3 = c.add_face(); + topo::face_handle<0, D> v0 = c.add_face(); + topo::face_handle<0, D> v1 = c.add_face(); + topo::face_handle<0, D> v2 = c.add_face(); + topo::face_handle<0, D> v3 = c.add_face(); // 1-faces (segments). - face_handle<1, D> e0 = c.add_face(v0 + v1); - face_handle<1, D> e1 = c.add_face(v0 + v2); - face_handle<1, D> e2 = c.add_face(v1 + v2); - face_handle<1, D> e3 = c.add_face(v0 + v3); - face_handle<1, D> e4 = c.add_face(v2 + v3); + topo::face_handle<1, D> e0 = c.add_face(v0 + v1); + topo::face_handle<1, D> e1 = c.add_face(v0 + v2); + topo::face_handle<1, D> e2 = c.add_face(v1 + v2); + topo::face_handle<1, D> e3 = c.add_face(v0 + v3); + topo::face_handle<1, D> e4 = c.add_face(v2 + v3); // 2-faces (triangles). - face_handle<2, D> t0 = c.add_face(e0 + e1 + e2); - face_handle<2, D> t1 = c.add_face(e1 + e3 + e4); + topo::face_handle<2, D> t0 = c.add_face(e0 + e1 + e2); + topo::face_handle<2, D> t1 = c.add_face(e1 + e3 + e4); std::cout << c << std::endl; @@ -107,12 +107,12 @@ int main() `-------------------*/ // Get the face data from (``static'') face handle E0. - const face<1, D>& face1 = e0.to_face(); + const topo::face<1, D>& face1 = e0.to_face(); // Any-face handle. - any_face_handle<D> af(e0); + topo::any_face_handle<D> af(e0); // Get the face data from (``dynamic'') face handle AF. - const face<1, D>& face2 = af.to_face<1>(); + const topo::face<1, D>& face2 = af.to_face<1>(); mln_assertion(&face1 == &face2); @@ -128,8 +128,8 @@ int main() // 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); - mln_bkd_citer_(complex<D>) bkd_f(c); + mln_fwd_citer_(topo::complex<D>) fwd_f(c); + mln_bkd_citer_(topo::complex<D>) bkd_f(c); for_all_2(fwd_f, bkd_f) std::cout << fwd_f << ' ' << bkd_f << std::endl; std::cout << std::endl; @@ -165,12 +165,12 @@ int main() template <unsigned N, unsigned D> void -test_faces_iter(complex<D>& c) +test_faces_iter(topo::complex<D>& c) { std::cout << "test_faces_iter<" << N << ", " << D << ">:" << std::endl; - mln_fwd_fiter(N, complex<D>) fwd_nf(c); - mln_bkd_fiter(N, complex<D>) bkd_nf(c); + mln_fwd_fiter(N, topo::complex<D>) fwd_nf(c); + mln_bkd_fiter(N, topo::complex<D>) bkd_nf(c); for_all_2(fwd_nf, bkd_nf) std::cout << fwd_nf << ' ' << bkd_nf << std::endl; std::cout << std::endl; @@ -178,15 +178,15 @@ test_faces_iter(complex<D>& c) template <unsigned N, unsigned D> void -test_complex_faces_iter(complex<D>& c) +test_complex_faces_iter(topo::complex<D>& c) { std::cout << "test_complex_faces_iter<" << N << ", " << D << ">:" << std::endl; /* FIXME: Provide sugar. Maybe redefined mln_fwd_fiter and mln_bkd_fiter so that they expand as complex_faces_iters (instead of faces_iters). */ - complex_faces_fwd_iter_<N, D> fwd_ncf(c); - complex_faces_bkd_iter_<N, D> bkd_ncf(c); + topo::complex_faces_fwd_iter_<N, D> fwd_ncf(c); + topo::complex_faces_bkd_iter_<N, D> bkd_ncf(c); for_all_2(fwd_ncf, bkd_ncf) std::cout << fwd_ncf << ' ' << bkd_ncf << std::endl; std::cout << std::endl; -- 1.6.0.1
participants (1)
-
Roland Levillain