
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Add a dimension-agnostic face handle. * mln/core/face.hh (mln::any_face_handle<D>): New class. (operator==(const any_face_handle<D>&, const any_face_handle<D>&)) (operator< (const any_face_handle<D>&, const any_face_handle<D>&)): New. (mln::face_handle<N, D>::face_handle): Use std::numeric_limits instead of UINT_MAX. face.hh | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 190 insertions(+), 4 deletions(-) Index: mln/core/face.hh --- mln/core/face.hh (revision 2126) +++ mln/core/face.hh (working copy) @@ -31,12 +31,24 @@ /// \file mln/core/face.hh /// \brief Face of a complex. -#include <climits> +#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 { @@ -58,8 +70,6 @@ } - // FIXME: Rename `face' as `face_data' and `face_handle' as face. - /*-------. | Face. | `-------*/ @@ -234,6 +244,78 @@ /// \} + /*----------------------. + | ``Any-face'' handle. | + `----------------------*/ + + // Face handle in a complex, where the dimension is dynamic. + template <unsigned D> + struct any_face_handle + { + /// 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); + + /// 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; + + /// Accessors. + /// \{ + /// Return the complex the face belongs to. + complex<D>& cplx() const; + /// Return the dimension of the face. + unsigned n() const; + /// Return the id of the face. + unsigned face_id() const; + + // FIXME: Implement. +// /// 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. + unsigned n_; + /// \brief The id of the face. + 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 @@ -266,7 +348,7 @@ template <unsigned N, unsigned D> face_handle<N, D>::face_handle() - : cplx_(0), face_id_(UINT_MAX) + : cplx_(0), face_id_(std::numeric_limits<unsigned>::max()) { // Ensure N is compatible with D. metal::bool_< N <= D >::check(); @@ -342,6 +424,7 @@ 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(); } @@ -350,6 +433,7 @@ 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(); } @@ -396,6 +480,108 @@ return fs2; } + + /*----------------------. + | ``Any-face'' handle. | + `----------------------*/ + + template <unsigned D> + 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> + 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. + } + + template <unsigned D> + any_face_handle<D>::any_face_handle(const any_face_handle<D>& rhs) + : cplx_(rhs.cplx_), face_id_(rhs.face_id_) + { + } + + template <unsigned D> + 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> + bool + any_face_handle<D>::is_valid() const + { + return cplx_ != 0 && face_id_ < cplx_->nfaces(n_); + } + + template <unsigned D> + complex<D>& + any_face_handle<D>::cplx() const + { + mln_precondition(cplx_); + return *cplx_; + } + + template <unsigned D> + unsigned + any_face_handle<D>::n() const + { + return n_; + } + + template <unsigned D> + unsigned + any_face_handle<D>::face_id() const + { + return face_id_; + } + +// template <unsigned D> +// template <unsigned n> +// face<N, D>& +// any_face_handle<D>::to_face() const +// { +// // FIXME: Adjust. +// // mln_precondition(is_valid()); +// // return cplx_->template face_<N>(face_id_); +// } + + + template <unsigned D> + 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> + 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