https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add more services to complexes.
* mln/core/complex.hh
(mln::complex<D>::nfaces())
(mln::complex<D>::nfaces(unsigned)):
New methods.
(mln::complex<D>::fold_left_)
(mln::complex<D>::apply_if_dim_matches_)
(mln::internal::faces_set_mixin<N, D>::fold_left_):
(mln::internal::faces_set_mixin<N, D>::apply_if_dim_matches_):
New methods.
(mln::internal::add_size)
(mln::internal::get_size):
New meta-functors.
complex.hh | 323 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 316 insertions(+), 7 deletions(-)
Index: mln/core/complex.hh
--- mln/core/complex.hh (revision 2125)
+++ mln/core/complex.hh (working copy)
@@ -38,6 +38,7 @@
# include <cstddef>
+# include <limits>
# include <iosfwd>
# include <mln/metal/bool.hh>
@@ -67,7 +68,6 @@
public:
/// Complex construction.
/// \{
-
/// \brief Add a 0-face to the complex.
face_handle<0u, D> add_face();
@@ -79,9 +79,31 @@
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.
/// \{
@@ -104,6 +126,32 @@
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
@@ -146,8 +194,8 @@
/// Faces of highest dimension (\p D).
template <unsigned D>
- struct faces_set_mixin<D, D> : faces_set_mixin<D - 1, D>,
- lower_dim_faces_set_mixin<D, 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_;
@@ -157,13 +205,26 @@
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 : faces_set_mixin<N - 1, D>,
- lower_dim_faces_set_mixin<N, D>,
- higher_dim_faces_set_mixin<N, 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_;
@@ -175,11 +236,24 @@
/// (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> : higher_dim_faces_set_mixin<0u, D>
+ struct faces_set_mixin<0u, D> : public higher_dim_faces_set_mixin<0u, D>
{
std::vector< face<0u, D> > faces_;
@@ -189,6 +263,19 @@
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.
@@ -203,6 +290,19 @@
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;
+ /// \}
};
/// \}
@@ -233,6 +333,10 @@
# ifndef MLN_INCLUDE_ONLY
+ /*-----------------------.
+ | Complex construction. |
+ `-----------------------*/
+
template <unsigned D>
face_handle<0u, D>
complex<D>::add_face()
@@ -278,6 +382,64 @@
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
@@ -286,6 +448,25 @@
return 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>&
@@ -462,6 +643,134 @@
} // 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 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 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