URL: https://svn.lrde.org/svn/oln/trunk/milena
ChangeLog:
2007-10-22 Simon Nivault <simon.nivault(a)lrde.epita.fr>
Update fllt and add conversion and set_p routines.
* mln/convert/to_set_p.hh: New.
* mln/convert/to_std_set.hh: Update.
* mln/core/concept/point_set.hh: Add todo.
* mln/set/diff.hh,
* mln/set/inter.hh,
* mln/set/sym_diff.hh: Work for mln::Point_Set.
* mln/set/union.hh: Like above and rename as...
* mln/set/uni.hh: ...this.
* sandbox/garrigues/fllt.hh: Update.
---
mln/convert/to_set_p.hh | 129 ++++++++++++++++++++++++++++++++++++++++++
mln/convert/to_std_set.hh | 13 ++++
mln/core/concept/point_set.hh | 3
mln/set/diff.hh | 25 ++++++++
mln/set/inter.hh | 24 +++++++
mln/set/sym_diff.hh | 21 ++++++
mln/set/uni.hh | 107 ++++++++++++++++++++++++++++++++++
sandbox/garrigues/fllt.hh | 41 +++++++------
8 files changed, 345 insertions(+), 18 deletions(-)
Index: trunk/milena/mln/core/concept/point_set.hh
===================================================================
--- trunk/milena/mln/core/concept/point_set.hh (revision 1372)
+++ trunk/milena/mln/core/concept/point_set.hh (revision 1373)
@@ -31,6 +31,9 @@
/*! \file mln/core/concept/point_set.hh
*
* \brief Definition of the concept of mln::Point_Set.
+ *
+ * \todo Think about adding an 'insert' method (not os easy because of
+ * pset_if...)
*/
# include <mln/core/concept/point.hh>
Index: trunk/milena/mln/convert/to_std_set.hh
===================================================================
--- trunk/milena/mln/convert/to_std_set.hh (revision 1372)
+++ trunk/milena/mln/convert/to_std_set.hh (revision 1373)
@@ -50,6 +50,9 @@
template <typename W>
std::set<mln_dpoint(W)> to_std_set(const Window<W>& win);
+ /// Convert a point set \p pset into a std::set of points.
+ template <typename W>
+ std::set<mln_point(W)> to_std_set(const Point_Set<W>& setp);
# ifndef MLN_INCLUDE_ONLY
@@ -65,6 +68,16 @@
return s;
}
+ template <typename W>
+ std::set<mln_point(W)> to_std_set(const Point_Set<W>& setp)
+ {
+ typedef mln_point(W) P;
+ std::set<P> s;
+ mln_piter(W) p(exact(setp));
+ for_all(p)
+ s.insert(p);
+ return s;
+ }
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::convert
Index: trunk/milena/mln/convert/to_set_p.hh
===================================================================
--- trunk/milena/mln/convert/to_set_p.hh (revision 0)
+++ trunk/milena/mln/convert/to_set_p.hh (revision 1373)
@@ -0,0 +1,129 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CONVERT_TO_SET_P_HH
+# define MLN_CONVERT_TO_SET_P_HH
+
+/*! \file mln/convert/to_set_p.hh
+ *
+ * \brief Conversions to mln::set_p.
+ */
+
+# include <set>
+
+# include <mln/core/concept/dpoint.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/set_p.hh>
+# include <mln/pw/image.hh>
+# include <mln/pw/cst.hh>
+# include <mln/metal/is_a.hh>
+
+
+namespace mln
+{
+
+ namespace convert
+ {
+
+ /// Convert a neighborhood \p nbh into a point set.
+ template <typename N>
+ set_p<mln_point(N)> to_window(const Neighborhood<N>& nbh);
+
+ /// Convert a binary image \p ima into a point set.
+ template <typename I>
+ set_p<mln_point(I)> to_set_p(const Image<I>& ima);
+
+ /// Convert a Window \p win into a point set.
+ template <typename P>
+ set_p<P> to_set_p(const Window<mln_dpoint(P)> win);
+
+ /// Convert an std::set \p s of points into a point set.
+ template <typename D>
+ set_p<D> to_set_p(const std::set<D>& s);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename N>
+ set_p<mln_point(N)> to_set_p(const Neighborhood<N>& nbh_)
+ {
+ const N& nbh = exact(nbh_);
+ typedef mln_dpoint(N) D;
+ typedef mln_point(N) P;
+ set_p<P> pset;
+ mln_niter(N) n(nbh, P::origin);
+ for_all(n)
+ pset.insert(n - P::origin);
+ return pset;
+ }
+
+ template <typename I>
+ set_p<mln_point(I)> to_set_p(const Image<I>& ima_)
+ {
+ const I& ima = exact(ima_);
+ mln_precondition(ima.has_data());
+ // FIXME: Check that ima is binary!
+ typedef mln_dpoint(I) D;
+ typedef mln_point(I) P;
+ set_p<P> pset;
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ if (ima(p))
+ pset.insert(p - P::origin);
+ return pset;
+ }
+
+ template <typename P>
+ set_p<P> to_set_p(const Window<mln_dpoint(P)>& win)
+ {
+ typedef mln_dpoint(P) D;
+ set_p<P> pset;
+ mln_qiter(D) q(exact(win), P::origin);
+ for_all(q)
+ pset.insert(q - P::origin);
+ return pset;
+ }
+
+ template <typename P>
+ set_p<P> to_set_p(const std::set<P>& s)
+ {
+ mln::metal::is_a<P, Point>::check();
+ set_p<P> pset;
+ for (typename std::set<P>::const_iterator i = s.begin();
+ i != s.end(); ++i)
+ pset.insert(*i);
+ return pset;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::convert
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CONVERT_TO_SET_P_HH
Index: trunk/milena/mln/set/union.hh (deleted)
===================================================================
Index: trunk/milena/mln/set/inter.hh
===================================================================
--- trunk/milena/mln/set/inter.hh (revision 1372)
+++ trunk/milena/mln/set/inter.hh (revision 1373)
@@ -36,6 +36,7 @@
# include <mln/convert/to_std_set.hh>
# include <mln/convert/to_window.hh>
+# include <mln/convert/to_set_p.hh>
# include <mln/metal/equal.hh>
@@ -54,6 +55,13 @@
window<mln_dpoint(Wl)>
inter(const Window<Wl>& lhs, const Window<Wr>& rhs);
+ /*! \brief Intersection between a couple of point sets.
+ *
+ * \relates mln::Point_Set
+ */
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ inter(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs);
# ifndef MLN_INCLUDE_ONLY
@@ -73,6 +81,22 @@
return convert::to_window(s);
}
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ inter(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs)
+ {
+ mln::metal::equal<mln_point(Wl), mln_point(Wr)>::check();
+ typedef mln_point(Wl) P;
+ std::set<P>
+ sl = convert::to_std_set(lhs),
+ sr = convert::to_std_set(rhs),
+ s;
+ std::set_intersection(sl.begin(), sl.end(),
+ sr.begin(), sr.end(),
+ std::inserter(s, s.begin()));
+ return convert::to_set_p(s);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::set
Index: trunk/milena/mln/set/diff.hh
===================================================================
--- trunk/milena/mln/set/diff.hh (revision 1372)
+++ trunk/milena/mln/set/diff.hh (revision 1373)
@@ -32,10 +32,13 @@
*
* \brief Set theoretic difference (non-symmetrical) of a couple of
* sets.
+ *
+ * \todo Add a diff(Point_Set& in_place, Function_p2b).
*/
# include <mln/convert/to_std_set.hh>
# include <mln/convert/to_window.hh>
+# include <mln/convert/to_set_p.hh>
# include <mln/metal/equal.hh>
@@ -51,6 +54,11 @@
window<mln_dpoint(Wl)>
diff(const Window<Wl>& lhs, const Window<Wr>& rhs);
+ /// Set theoretic difference of \p lhs and \p rhs.
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ diff(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs);
+
# ifndef MLN_INCLUDE_ONLY
@@ -70,6 +78,23 @@
return convert::to_window(s);
}
+ /// Set theoretic difference of \p lhs and \p rhs.
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ diff(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs)
+ {
+ mln::metal::equal<mln_point(Wl), mln_point(Wr)>::check();
+ typedef mln_point(Wl) P;
+ std::set<P>
+ sl = convert::to_std_set(lhs),
+ sr = convert::to_std_set(rhs),
+ s;
+ std::set_difference(sl.begin(), sl.end(),
+ sr.begin(), sr.end(),
+ std::inserter(s, s.begin()));
+ return convert::to_set_p(s);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::set
Index: trunk/milena/mln/set/uni.hh
===================================================================
--- trunk/milena/mln/set/uni.hh (revision 0)
+++ trunk/milena/mln/set/uni.hh (revision 1373)
@@ -0,0 +1,107 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_SET_UNI_HH
+# define MLN_SET_UNI_HH
+
+/*! \file mln/set/uni.hh
+ *
+ * \brief Several routines to compute the union of a couple of sets.
+ */
+
+# include <mln/convert/to_std_set.hh>
+# include <mln/convert/to_window.hh>
+# include <mln/convert/to_set_p.hh>
+# include <mln/metal/equal.hh>
+
+
+
+namespace mln
+{
+
+ namespace set
+ {
+
+ /*! \brief Union of a couple of windows.
+ *
+ * \relates mln::Window
+ */
+ template <typename Wl, typename Wr>
+ window<mln_dpoint(Wl)>
+ uni(const Window<Wl>& lhs, const Window<Wr>& rhs);
+
+ /*! \brief Union of a couple of point sets.
+ *
+ * \relates mln::Point_Set
+ */
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ uni(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename Wl, typename Wr>
+ window<mln_dpoint(Wl)>
+ uni(const Window<Wl>& lhs, const Window<Wr>& rhs)
+ {
+ mln::metal::equal<mln_dpoint(Wl), mln_dpoint(Wr)>::check();
+ typedef mln_dpoint(Wl) D;
+ std::set<D>
+ sl = convert::to_std_set(lhs),
+ sr = convert::to_std_set(rhs),
+ s;
+ std::set_union(sl.begin(), sl.end(),
+ sr.begin(), sr.end(),
+ std::inserter(s, s.begin()));
+ return convert::to_window(s);
+ }
+
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ uni(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs)
+ {
+ mln::metal::equal<mln_point(Wl), mln_point(Wr)>::check();
+ typedef mln_point(Wl) P;
+ std::set<P>
+ sl = convert::to_std_set(lhs),
+ sr = convert::to_std_set(rhs),
+ s;
+ std::set_union(sl.begin(), sl.end(),
+ sr.begin(), sr.end(),
+ std::inserter(s, s.begin()));
+ return convert::to_set_p(s);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::set
+
+} // end of namespace mln
+
+
+#endif // ! MLN_SET_UNI_HH
Index: trunk/milena/mln/set/sym_diff.hh
===================================================================
--- trunk/milena/mln/set/sym_diff.hh (revision 1372)
+++ trunk/milena/mln/set/sym_diff.hh (revision 1373)
@@ -35,6 +35,7 @@
# include <mln/convert/to_std_set.hh>
# include <mln/convert/to_window.hh>
+# include <mln/convert/to_set_p.hh>
# include <mln/metal/equal.hh>
@@ -50,6 +51,10 @@
window<mln_dpoint(Wl)>
sym_diff(const Window<Wl>& lhs, const Window<Wr>& rhs);
+ /// Set theoretic symmetrical difference of \p lhs and \p rhs.
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ sym_diff(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs);
# ifndef MLN_INCLUDE_ONLY
@@ -69,6 +74,22 @@
return convert::to_window(s);
}
+ template <typename Wl, typename Wr>
+ set_p<mln_point(Wl)>
+ sym_diff(const Point_Set<Wl>& lhs, const Point_Set<Wr>& rhs)
+ {
+ mln::metal::equal<mln_point(Wl), mln_point(Wr)>::check();
+ typedef mln_point(Wl) P;
+ std::set<P>
+ sl = convert::to_std_set(lhs),
+ sr = convert::to_std_set(rhs),
+ s;
+ std::set_symmetric_difference(sl.begin(), sl.end(),
+ sr.begin(), sr.end(),
+ std::inserter(s, s.begin()));
+ return convert::to_set_p(s);
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::set
Index: trunk/milena/sandbox/garrigues/fllt.hh
===================================================================
--- trunk/milena/sandbox/garrigues/fllt.hh (revision 1372)
+++ trunk/milena/sandbox/garrigues/fllt.hh (revision 1373)
@@ -52,6 +52,9 @@
# include <mln/level/fill.hh>
# include <mln/accu/min.hh>
+# include <mln/set/uni.hh>
+# include <mln/set/diff.hh>
+
# include <mln/labeling/regional_minima.hh>
# include <mln/labeling/level.hh>
@@ -153,8 +156,15 @@
N.insert (n);
}
+ std::cout << "A :" << std::endl;
+ if (A.npoints())
+ debug::println(ima | A);
std::cout << "N :" << std::endl;
+ if (N.npoints())
debug::println(ima | N);
+ std::cout << "R :" << std::endl;
+ if (R.npoints())
+ debug::println(ima | R);
// gn <- min u(x) x belongs to N.
gn = level::compute<accu::min>(ima | N);
@@ -208,9 +218,16 @@
g = gn;
// A <- {x belongs to N / u(x) == g}
- A.clear();
-// A += N | (pw::value(u) == pw::cst(g));
+ A = set::uni(A, N | pw::value(u) == pw::cst(g));
// N <- N\{x belongs to N / u(x) == g}
+ N = set::diff(N, N | pw::value(u) == pw::cst(g));
+
+ std::cout << "A :" << std::endl;
+ if (A.npoints())
+ debug::println(u | A);
+ std::cout << "N :" << std::endl;
+ if (N.npoints())
+ debug::println(u | N);
std::cout << "exiting step 4_1" << std::endl;
}
@@ -218,7 +235,7 @@
/// IF g == gn.
template <typename V, typename P>
- void step4_2 (const image2d<V>& ima,
+ void step4_2 (const image2d<V>& u,
set_p<P>& A,
set_p<P>& N,
V& g)
@@ -226,21 +243,9 @@
std::cout << "entering step 4_2" << std::endl;
// A <- {x belongs to N / u(x) == g}
+ A = set::uni(A, N | pw::value(u) == pw::cst(g));
// N <- N\{x belongs to N / u(x) == g}
-
- set_p<P> N_tmp (N);
-
- A.clear();
- N.clear();
- mln_piter(set_p<P>) p(N_tmp);
- for_all(p)
- {
- if (ima (p) == g)
- {
- A.insert(p);
- N.insert(p);
- }
- }
+ N = set::diff(N, N | pw::value(u) == pw::cst(g));
std::cout << "exiting step 4_2" << std::endl;
}
@@ -323,7 +328,7 @@
if (g == gn)
{
- step4_2(ima, A, N, g);
+ step4_2(u, A, N, g);
// GO TO 3)
continue;
}
Matthieu Garrigues wrote:
> URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
>
> ChangeLog:
> 2007-10-16 Matthieu Garrigues <garrigues(a)lrde.epita.fr>
>
> Fix in fi_adaptor.
> * mln/core/fi_adaptor.hh: Fix
> * tests/fi_adaptor.cc: Fix
> ...
Please add a guard so that this file can compile
even if the third library is not available
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-10-22 Guillaume Duhamel <guillaume.duhamel(a)lrde.epita.fr>
Move abr in mln.
* mln/util/abr.hh: New.
* tests/abr.cc: New.
---
mln/util/abr.hh | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/abr.cc | 54 +++++++++++++++++++
2 files changed, 212 insertions(+)
Index: trunk/milena/tests/abr.cc
===================================================================
--- trunk/milena/tests/abr.cc (revision 0)
+++ trunk/milena/tests/abr.cc (revision 1366)
@@ -0,0 +1,54 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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.
+
+/*!
+ * \file tests/abr.cc
+ *
+ * \brief test of mln::util::abr
+ *
+ */
+
+#include <mln/util/abr.hh>
+
+int main (void)
+{
+ using namespace mln;
+ unsigned elt1 = 1;
+ unsigned elt2 = 2;
+ unsigned elt3 = 3;
+ unsigned elt4 = 4;
+ unsigned elt5 = 5;
+ util::s_abr<unsigned> abr (elt1);
+
+ abr.add_son (elt2);
+ abr.add_son (elt3);
+ abr.print ();
+ util::s_abr<unsigned>* abr2 = abr.search (elt2);
+ abr2->add_son (elt4);
+ abr2->add_son (elt5);
+ abr.print ();
+}
Index: trunk/milena/mln/util/abr.hh
===================================================================
--- trunk/milena/mln/util/abr.hh (revision 0)
+++ trunk/milena/mln/util/abr.hh (revision 1366)
@@ -0,0 +1,158 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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_UTIL_ABR_HH
+# define MLN_UTIL_ABR_HH
+
+# include <list>
+# include <iostream>
+
+/*!
+ * \file mln/util/abr.hh
+ *
+ * \brief Definition of a generic general tree.
+ *
+ *
+ */
+
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ template <typename T>
+ struct s_abr
+ {
+ s_abr ();
+ s_abr (T& elt);
+
+ void add_son (T& elt);
+ void print_rec (int n) const;
+ void print (void) const;
+ int search_rec(s_abr<T>** res, T& elt);
+ s_abr<T>* search(T& elt);
+
+ T& elt_;
+ s_abr<T>* father_;
+ std::list< s_abr<T>* > sons_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T>
+ s_abr<T>::s_abr ()
+ : elt_ (0),
+ father_ (0)
+ {
+ }
+
+ template <typename T>
+ s_abr<T>::s_abr (T& elt)
+ : elt_ (elt),
+ father_ (0)
+ {
+ }
+
+
+ template <typename T>
+ void
+ s_abr<T>::add_son (T& elt)
+ {
+
+ s_abr<T>* s = new s_abr<T> (elt);
+
+ s->father_ = this;
+ this->sons_.push_back (s);
+ }
+
+ template <typename T>
+ void
+ s_abr<T>::print_rec (int n) const
+ {
+ std::cout << this->elt_ << std::endl;
+ typename std::list<s_abr<T>* >::const_iterator it = this->sons_.begin ();
+ for (; it != this->sons_.end (); ++it)
+ {
+ for (int i = 0; i < n; ++i)
+ std::cout << " ";
+ (**it).print_rec (n + 1);
+ }
+ }
+
+ template <typename T>
+ void
+ s_abr<T>::print (void) const
+ {
+ this->print_rec(1);
+ }
+
+
+ template <typename T>
+ int
+ s_abr<T>::search_rec(s_abr<T>** res, T& elt)
+ {
+ if (elt == this->elt_)
+ {
+ *res = this;
+ return 1;
+ }
+ else
+ {
+ typename std::list<s_abr<T>* >::iterator it = this->sons_.begin ();
+ for (; it != this->sons_.end (); ++it)
+ {
+ if ((**it).search_rec (res, elt))
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ template <typename T>
+ s_abr<T>*
+ s_abr<T>::search(T& elt)
+ {
+ s_abr<T>* res = 0;
+
+ if (search_rec (&res, elt))
+ return res;
+ std::cerr << elt << " not found" << std::endl;
+ return 0;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::util
+
+
+} // end of namespace mln
+
+
+#endif // !MLN_UTIL_ABR_HH