r4620: Alternate representation of tree (some tries...)

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-10-07 Edwin Carlinet <carlinet@lrde.epita.fr> Alternate representation of tree (some tries...). * edwin/exec/benchmark/Makefile, * edwin/exec/benchmark/newv.cc, * edwin/exec/benchmark/oldv.cc, * edwin/exec/benchmark: Applications, and comparaisons between the old and new version. * edwin/mln/core, * edwin/mln/core/concept/dindex_site.hh, * edwin/mln/core/concept/index_site.hh, * edwin/mln/core/dindex_site.hh, * edwin/mln/core/internal/index_site_base.hh, * edwin/mln/core/internal, * edwin/mln/core/site_set/p_run_idx.hh, * edwin/mln/core/site_set/p_run_idx_piter.hh, * edwin/mln/core/site_set: Temporary type for index site (used by the node type), its site set and its iterators. * edwin/mln/core/concept/tree.hh, * edwin/mln/core/concept: Tree concept. * edwin/mln/core/image, * edwin/mln/core/image/attribute_image.hh: Attribute image type. * edwin/mln/debug, * edwin/mln/debug/ctree.hh: Debug tools with println overloads. * edwin/mln/morpho/tree/component_tree.hh: Shortcuts for building min and max tree. * edwin/mln/morpho/tree/compute_attribute_image.hh: Compute an attribute using the new tree representation. * edwin/mln/morpho/tree/impl, * edwin/mln/morpho/tree/impl/union_find.hh: (Simple) tree computation based on union-find method. * edwin/mln/morpho/tree/propagate_node.hh: Temporary methods for fast propagation. Will be useless as soon as the subdomain morpher will be specialized. * edwin/mln/util, * edwin/mln/util/ctree, * edwin/mln/util/ctree/ctree.hh, * edwin/mln/util/ctree/internal, * edwin/mln/util/ctree/internal/tree_base.hh, * edwin/mln/util/ctree/node.hh: Materials for the new tree representation. --- exec/benchmark/Makefile | 21 + exec/benchmark/newv.cc | 86 ++++ exec/benchmark/oldv.cc | 82 ++++ mln/core/concept/dindex_site.hh | 253 ++++++++++++ mln/core/concept/index_site.hh | 311 +++++++++++++++ mln/core/concept/tree.hh | 148 +++++++ mln/core/dindex_site.hh | 119 +++++ mln/core/image/attribute_image.hh | 435 +++++++++++++++++++++ mln/core/internal/index_site_base.hh | 254 ++++++++++++ mln/core/site_set/p_run_idx.hh | 458 ++++++++++++++++++++++ mln/core/site_set/p_run_idx_piter.hh | 222 ++++++++++ mln/debug/ctree.hh | 155 +++++++ mln/morpho/tree/component_tree.hh | 124 ++++++ mln/morpho/tree/compute_attribute_image.hh | 178 ++++++++ mln/morpho/tree/impl/dual_hqueue.hh | 408 ++++++++++++++++++++ mln/morpho/tree/impl/dual_union_find.hh | 361 +++++++++++++++++ mln/morpho/tree/impl/union_find.hh | 172 ++++++++ mln/morpho/tree/propagate_node.hh | 112 +++++ mln/util/ctree/ctree.hh | 589 +++++++++++++++++++++++++++++ mln/util/ctree/internal/tree_base.hh | 140 ++++++ mln/util/ctree/node.hh | 183 +++++++++ 21 files changed, 4811 insertions(+) Index: trunk/milena/sandbox/edwin/exec/benchmark/newv.cc =================================================================== --- trunk/milena/sandbox/edwin/exec/benchmark/newv.cc (revision 0) +++ trunk/milena/sandbox/edwin/exec/benchmark/newv.cc (revision 4620) @@ -0,0 +1,86 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/image/attribute_image.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/value/int_u8.hh> + +#include <mln/util/ctree/ctree.hh> + +#include <mln/morpho/tree/component_tree.hh> +#include <mln/morpho/tree/compute_attribute_image.hh> +#include <mln/morpho/tree/filter/min.hh> +#include <mln/morpho/attribute/volume.hh> +#include <mln/morpho/attribute/card.hh> + + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/pw/all.hh> +#include <mln/core/var.hh> + +#include <mln/util/timer.hh> +#include <iostream> + +#include <mln/debug/ctree.hh> +#include <mln/debug/println.hh> + +void usage(char** argv) +{ + std::cout << "Usage: " << argv[0] << " image lambda [new.pgm]" + << std::endl; + abort(); +} + +static mln::util::timer tm; + +void bench(const char* msg) +{ + std::cout << msg << " in " << tm << " s" << std::endl; + tm.restart(); +} + +int main(int argc, char** argv) +{ + using namespace mln; + using value::int_u8; + + if (argc < 3) + usage(argv); + + const char* finput = argv[1]; + const unsigned lambda = atoi(argv[2]); + const char* foutput = (argc > 3) ? argv[3] : "new.pgm"; + + tm.start(); + + + typedef image2d<int_u8> I; + I input; + io::pgm::load(input, finput); + bench("Image Loadin"); + + // Tree Computation + typedef util::ctree::ctree<I> tree_t; + tree_t tree = morpho::tree::max_tree(input, c4()); + bench("Tree construction"); + + // Compute Attribute + typedef attribute_image<tree_t, unsigned> A; + morpho::attribute::volume<I> attribute; + A attr_img = morpho::tree::compute_attribute_image(tree, attribute); + bench("Attribute Computation (volume)"); + + // Filtering + attribute_image<tree_t, int_u8> out = tree.to_image(); + mln_VAR(predicate, pw::value(attr_img) > pw::cst(lambda)); + morpho::tree::filter::min(out, predicate); + bench("Filtering"); + + // Converting + I output; + convert::over_load::from_to_(out, output); // FIXME ! + bench("Restore"); + + io::pgm::save(output, foutput); + bench("Image Savin"); +} Index: trunk/milena/sandbox/edwin/exec/benchmark/oldv.cc =================================================================== --- trunk/milena/sandbox/edwin/exec/benchmark/oldv.cc (revision 0) +++ trunk/milena/sandbox/edwin/exec/benchmark/oldv.cc (revision 4620) @@ -0,0 +1,82 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/value/int_u8.hh> + +#include <mln/morpho/tree/data.hh> +#include <mln/morpho/tree/component_tree.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/morpho/tree/compute_attribute_image.hh> +#include <mln/morpho/tree/propagate_representative.hh> +#include <mln/morpho/tree/filter/min.hh> +#include <mln/morpho/attribute/volume.hh> +#include <mln/morpho/attribute/card.hh> + +#include <mln/pw/all.hh> +#include <mln/core/var.hh> + +#include <mln/debug/println.hh> +#include <mln/util/timer.hh> +#include <iostream> + +void usage(char** argv) +{ + std::cout << "Usage: " << argv[0] << " image lambda [old.pgm]" + << std::endl; + abort(); +} + +static mln::util::timer tm; + +void bench(const char* msg) +{ + std::cout << msg << " in " << tm << " s" << std::endl; + tm.restart(); +} + +int main(int argc, char** argv) +{ + using namespace mln; + using value::int_u8; + + if (argc < 3) + usage(argv); + + const char* finput = argv[1]; + const unsigned lambda = atoi(argv[2]); + const char* foutput = (argc > 3) ? argv[3] : "old.pgm"; + + tm.start(); + + + typedef image2d<int_u8> I; + I input; + io::pgm::load(input, finput); + bench("Image Loadin"); + + // Tree Computation + typedef morpho::tree::data<I, p_array<mln_psite_(I)> > tree_t; + tree_t tree = morpho::tree::max_tree(input, c4()); + bench("Tree construction"); + + // Compute Attribute + typedef mln_ch_value_(I, unsigned) A; + morpho::attribute::volume<I> attribute; + A attr_img = morpho::tree::compute_attribute_image(attribute, tree); + bench("Attribute Computation (volume)"); + + // Filtering + I out = duplicate(input); + mln_VAR(predicate, pw::value(attr_img) > pw::cst(lambda)); + morpho::tree::filter::min(tree, out, predicate); + bench("Filtering"); + + // Restore + morpho::tree::propagate_representative(tree, out); + bench("Restore"); + + io::pgm::save(out, foutput); + bench("Image Savin"); +} Index: trunk/milena/sandbox/edwin/exec/benchmark/Makefile =================================================================== --- trunk/milena/sandbox/edwin/exec/benchmark/Makefile (revision 0) +++ trunk/milena/sandbox/edwin/exec/benchmark/Makefile (revision 4620) @@ -0,0 +1,21 @@ +-include makefile.rules + +MLN_DIR = ~/olena/trunk/milena +CXXFLAGS += -W -Wall +CXXFLAGS += $(if $(DEBUG), -g -ggdb, -DNDEBUG $(if $(RELEASE), -O3, -O1)) +MY_CXXFLAGS := $(CXXFLAGS) -I $(MLN_DIR)/sandbox/edwin -I $(MLN_DIR) +CXXFLAGS += -I $(MLN_DIR) +CC = g++ +LDFLAGS = + +all: oldv newv + +newv.o: newv.cc + $(CXX) $(MY_CXXFLAGS) -c $< + +clean: + rm -f *.o + +newv: newv.o + +oldv: oldv.o Index: trunk/milena/sandbox/edwin/mln/morpho/tree/component_tree.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/component_tree.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/component_tree.hh (revision 4620) @@ -0,0 +1,124 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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. + + +/// \file +/// +/// Compute a canonized (parenthood) component tree from an image. + + +#ifndef MLN_MORPHO_TREE_COMPONENT_TREE_HH +# define MLN_MORPHO_TREE_COMPONENT_TREE_HH + +# include <mln/tag/tree.hh> +# include <mln/util/ctree/ctree.hh> +# include <mln/morpho/tree/impl/union_find.hh> +# include <mln/morpho/tree/impl/hqueue.hh> + +namespace mln +{ + + namespace morpho + { + + namespace tree + { + + /// Compute a canonized min-tree. + /// + /// \param[in] f The input image. + /// \param[in] nbh The neighborhood. + /// + /// \return The corresponding min-tree structure. + /// + template <typename I, typename N> + inline + util::ctree::ctree<I> + min_tree(const Image<I>& f, const Neighborhood<N>& nbh); + + /// Compute a canonized max-tree. + /// + /// \param[in] f The input image. + /// \param[in] nbh The neighborhood. + /// + /// \return The corresponding max-tree structure. + /// + template <typename I, typename N> + inline + util::ctree::ctree<I> + max_tree(const Image<I>& f, const Neighborhood<N>& nbh); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I, typename N> + inline + util::ctree::ctree<I> + min_tree(const Image<I>& f_, const Neighborhood<N>& nbh_) + { + trace::entering("morpho::tree::min_tree"); + + const I& f = exact(f_); + const N& nbh = exact(nbh_); + + mln_precondition(f.is_valid()); + mln_precondition(nbh.is_valid()); + + util::ctree::ctree<I> tree = + morpho::tree::impl::generic::union_find(tag::tree::min, f, nbh); + + trace::exiting("morpho::tree::min_tree"); + return tree; + } + + template <typename I, typename N> + inline + util::ctree::ctree<I> + max_tree(const Image<I>& f_, const Neighborhood<N>& nbh_) + { + trace::entering("morpho::tree::max_tree"); + + const I& f = exact(f_); + const N& nbh = exact(nbh_); + + mln_precondition(f.is_valid()); + mln_precondition(nbh.is_valid()); + + util::ctree::ctree<I> tree = + morpho::tree::impl::generic::union_find(tag::tree::max, f, nbh); + + trace::exiting("morpho::tree::max_tree"); + return tree; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::tree + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif // !MLN_MORPHO_TREE_COMPONENT_TREE_HH Index: trunk/milena/sandbox/edwin/mln/morpho/tree/compute_attribute_image.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/compute_attribute_image.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/compute_attribute_image.hh (revision 4620) @@ -0,0 +1,178 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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 COMPUTE_ATTRIBUTE_IMAGE_HH +# define COMPUTE_ATTRIBUTE_IMAGE_HH +/// +/// +/// \brief Compute an attribute on a morphological tree. +/// +/// \todo Specialize for fast image. +/// + + +# include <mln/core/image/attribute_image.hh> +# include <mln/core/concept/tree.hh> +# include <mln/core/concept/accumulator.hh> + +# include <mln/data/fill.hh> + +namespace mln +{ + + namespace morpho + { + + namespace tree + { + + template <typename T, typename A> + attribute_image<T, mln_result(A)> + compute_attribute_image(const Tree<T>& tree, + const Accumulator<A>& accu); + + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename T, typename A> + inline + void + take_as_init(trait::accumulator::when_pix::use_none, + const T&, A& accu, + const mln_psite(T)&) + { + accu.take(); + } + + template <typename T, typename A> + inline + void + take_as_init(trait::accumulator::when_pix::use_pix, + const T& tree, A& accu, + const mln_psite(T)& p) + { + accu.take(make::pix(p, tree.f(p))); + } + + + template <typename T, typename A> + inline + void + take_as_init(trait::accumulator::when_pix::use_v, + const T& tree, A& accu, + const mln_psite(T)& p) + { + accu.take(tree.f(p)); + } + + template <typename T, typename A> + inline + void + take_as_init(trait::accumulator::when_pix::use_p, + const T&, A& accu, + const mln_psite(T)& p) + { + accu.take(p); + } + + template <typename T, typename A> + void + take_as_init(const T& tree, A& a, const mln_psite(T)& p) + { + take_as_init(mln_trait_accumulator_when_pix(A)(), tree, a, p); + } + + } // end of namespace namespace mln::morpho::tree::internal + + namespace impl + { + + namespace generic + { + + template <typename T, typename A> + attribute_image<T, mln_result(A)> + compute_attribute_image(const T& tree, const A& accu, attribute_image<T, A>* accu_img = 0) + { + attribute_image<T, A> a(tree); + (void) accu_img; + + // Transmit dynamic data of accumulator (ex: rank filter). + data::fill(a, accu); + + // Initialize. Each node takes its content. + { + mln_fwd_piter(T::domain_t) p(tree.domain()); + for_all(p) + internal::take_as_init(tree, a.element(tree.node_at_(p)), p); + } + + // Transmit to parent. + for (unsigned i = tree.n_nodes() - 1; i > 0; --i) + { + unsigned q = tree.parent_at_(i); + if (q != i) // The current node is not a root. + a.element(q).take(a.element(i)); + } + + attribute_image<T, mln_result(A)> out(tree); + for (unsigned i = 0; i < tree.n_nodes(); i++) + out.element(i) = a.element(i).to_result(); + + return out; + } + + } // end of namespace mln::morpho::tree::impl::generic + + } // end of namespace mln::morpho::tree::impl + + + // Facades + template <typename T, typename A> + attribute_image<T, mln_result(A)> + compute_attribute_image(const Tree<T>& tree_, const Accumulator<A>& acc) + { + trace::entering("mln::morpho::tree::compute_attribute_image"); + const T& tree = exact(tree_); + const A& accu = exact(acc); + + mln_precondition(tree.is_valid()); + + return impl::generic::compute_attribute_image(tree, accu); + trace::exiting("mln::morpho::tree::compute_attribute_image"); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::tree + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif // !COMPUTE_ATTRIBUTE_IMAGE_HH Index: trunk/milena/sandbox/edwin/mln/morpho/tree/impl/dual_hqueue.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/impl/dual_hqueue.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/impl/dual_hqueue.hh (revision 4620) @@ -0,0 +1,408 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_MORPHO_TREE_IMPL_COMPUTE_PARENT_DUAL_HQUEUE_HH +# define MLN_MORPHO_TREE_IMPL_COMPUTE_PARENT_DUAL_HQUEUE_HH + +/// +/// \brief The dual input tree algorithm specialized for low quantized image. +/// +/// This implementation is based on P. Salembier algorithm using +/// hierachical queues. This implies a low-quantized input image so +/// that the number of queues is limited. +/// +/// TODO: Think about how to extend f domain in a more +/// generic way. The actual implementation doubles the size of the +/// first dimension. It implies a boxed domain. +/// +/// TODO: Use the less functor. The actual implementation is for max-tree. +/// +/// TODO: During the canonization pass, we build the tree site set +/// from the sorted site set of f, so that we compute twice f +/// histogram (can be avoided). + +# include <mln/data/sort_psites.hh> +# include <mln/data/fill.hh> + +# include <mln/geom/nsites.hh> +# include <mln/geom/translate.hh> + +# include <mln/morpho/tree/data.hh> + +# include <mln/util/hqueues.hh> +# include <mln/util/ord.hh> + +# include <mln/value/value_array.hh> +# include <mln/value/set.hh> + +# include <mln/util/timer.hh> + +namespace mln +{ + + namespace morpho + { + + namespace tree + { + + namespace impl + { + + /// Compute a tree using hqueues. + /// + /// \param f The original image. + /// \param m The connectivity mask. + /// \param nbh The neighborhood of the mask. + /// + /// \return The tree structure. + /// + template <typename I, typename N> + inline + data<I, p_array<mln_psite(I)> > + dual_hqueue(const Image<I>& f, + const Image<I>& m, + const Neighborhood<N>& nbh); + + } // end of namespace mln::morpho::tree::impl + + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename I, typename N, class E> + struct shared_flood_args + { + typedef mln_psite(I) P; + typedef mln_value(I) V; + typedef p_array<P> S; + + const I& f; + const I& m; + const N& nbh; + mln_ch_value(I, P)& parent; + + // Aux data + util::hqueues<P, V>& hqueues; + const E& extend; // site -> site functor. + value::value_array<V, bool> is_node_at_level; + value::value_array<V, P> node_at_level; + mln_ch_value(I, bool) deja_vu; + const value::set<V>& vset; + + shared_flood_args(const I& f_, + const I& m_, + const N& neigb_, + mln_ch_value(I, P)& parent_, + util::hqueues<mln_psite(I), V>& hqueues_, + const E& extend_) + : f (f_), + m (m_), + nbh (neigb_), + parent (parent_), + hqueues (hqueues_), + extend (extend_), + is_node_at_level (false), + vset (hqueues.vset()) + { + initialize(deja_vu, f); + mln::data::fill(deja_vu, false); + } + }; + + template <typename I> + inline + histo::array<mln_value(I)> + compute_histo(const I& f, const I& m, mln_value(I)& hmin, mln_psite(I)& pmin) + { + histo::array<mln_value(I)> hm = histo::compute(m); + const histo::array<mln_value(I)> hf = histo::compute(f); + + { // Retrieve hmin. + unsigned i = 0; + while (hm[i] == 0) + ++i; + hmin = hm.vset()[i]; + } + + // Merge histograms. + for (unsigned i = 0; i < hm.nvalues(); ++i) + hm[i] += hf[i]; + + // Retrieve pmin. + mln_piter(I) p(m.domain()); + for (p.start(); m(p) != hmin; p.next()) + ; + mln_assertion(p.is_valid()); + pmin = p; + + return hm; + } + + // Site -> site functor: give for all p in Domain(f), its + // equivalence in the extended domain. + // TODO: make it generic. It works only on boxed domain. + template <typename I> + struct extend + { + extend(const mln_psite(I)::delta& dp) + : dp_ (dp) + { + } + + mln_psite(I) operator() (const mln_psite(I)& p) const + { + return p + dp_; + } + + private: + const mln_psite(I)::delta dp_; + }; + + } // end of namespace mln::morpho::tree::internal + + namespace impl + { + + template <typename I, typename N, typename E> + unsigned + flood(internal::shared_flood_args<I, N, E>& args, const unsigned h_idx) + { + mln_assertion(args.is_node_at_level[h_idx]); + + while (!args.hqueues[h_idx].empty()) + { + mln_psite(I) p = args.hqueues[h_idx].pop_front(); + unsigned p_idx = args.vset.index_of(args.f(p)); + + if (p_idx != h_idx) + { // Intensity mismatch: irregular case. + mln_psite(I) pext = args.extend(p); + args.parent(pext) = args.node_at_level[h_idx]; + + if (p_idx > h_idx) // Singleton with parent at h. + args.parent(p) = args.node_at_level[h_idx]; + else + { + if (!args.is_node_at_level[p_idx]) + { + args.is_node_at_level[p_idx] = true; + args.node_at_level[p_idx] = p; + } + } + } + + if (p_idx <= h_idx) + { + if (!args.f.domain().has(args.node_at_level[p_idx]) || + util::ord_strict(p, args.node_at_level[p_idx])) + { // Regular case but a representative provided by the extension. + args.parent(args.node_at_level[p_idx]) = p; + args.node_at_level[p_idx] = p; + //args.parent(p) = p; + } + args.parent(p) = args.node_at_level[p_idx]; + } + + + // Process the neighbors + mln_niter(N) n(args.nbh, p); + for_all(n) + if (args.f.domain().has(n) && !args.deja_vu(n)) + { + unsigned mn = args.vset.index_of(args.m(n)); + unsigned fn = args.vset.index_of(args.f(n)); + args.hqueues[mn].push(n); + args.deja_vu(n) = true; + + mln_psite(I) ext = args.extend(n); + // Create a node at c. + { + mln_psite(I) node = (fn == mn) ? n : ext; + if (!args.is_node_at_level[mn]) + { + args.is_node_at_level[mn] = true; + args.node_at_level[mn] = node; + } + } + + while (mn > h_idx) + mn = flood(args, mn); + } + } + + // Retrieve dad. + args.is_node_at_level[h_idx] = false; + unsigned c = h_idx; + while (c > 0 && !args.is_node_at_level[c]) + --c; + + mln_psite(I) x = args.node_at_level[h_idx]; + if (c > 0) + args.parent(x) = args.node_at_level[c]; + else + args.parent(x) = x; + + return c; + } + + template <typename I, typename N> + inline + data< I, p_array<mln_psite(I)> > + dual_hqueue(const Image<I>& f_, + const Image<I>& m_, + const Neighborhood<N>& neibh_) + { + trace::entering("mln::morpho::tree::impl::dual_hqueue"); + + const I& f = exact(f_); + const I& m = exact(m_); + const N& nbh = exact(neibh_); + + typedef mln_psite(I) P; + typedef p_array<mln_psite(I)> S; + + util::timer tm; + tm.start(); + + // Histo. + mln_psite(I) pmin; + mln_value(I) hmin; + const histo::array<mln_value(I)> histo = internal::compute_histo(f, m, hmin, pmin); + util::hqueues<P, mln_value(I)> hqueues(histo); + + mln_psite(I)::delta dp(literal::zero); + mln_domain(I) d_ext = f.domain(); + mln_domain(I) d = f.domain(); + + // Extend the domain. + dp[0] = d.pmax()[0] - d.pmin()[0] + 1; + d.pmax() += dp; + d_ext.pmin() += dp; + d_ext.pmax() += dp; + + // Data. + mln_concrete(I) fext; + mln_ch_value(I, P) parent; + p_array<mln_psite(I)> s; + + // Initialization. + fext = geom::translate(m, dp.to_vec(), f, d); + initialize(parent, fext); + s.reserve(geom::nsites(fext)); + + // Process. + internal::extend<I> extend(dp); + internal::shared_flood_args< I, N, internal::extend<I> > + args(f, m, nbh, parent, hqueues, extend); + + unsigned r = args.vset.index_of(hmin); + args.deja_vu(pmin) = true; + args.hqueues[r].push(pmin); + args.node_at_level[r] = (f(pmin) == hmin) ? pmin : extend(pmin); + args.is_node_at_level[r] = true; + flood(args, r); + + // Attach the nodes under hmin. + unsigned i = r; + do + { + if (args.is_node_at_level[i]) + { + parent(args.node_at_level[r]) = args.node_at_level[i]; + r = i; + } + } + while (i-- > 0); + parent(args.node_at_level[r]) = args.node_at_level[r]; //root + + // Canonization and make tree site set. + { + mln_ch_value(I, bool) deja_vu(d_ext); + mln::data::fill(deja_vu, false); + + p_array<mln_psite(I)> s_f = mln::data::sort_psites_increasing(f); + mln_fwd_piter(S) p(s_f); // Forward. + for_all(p) + { + P x = p; + P q = parent(p); + + // Case: l: m <---- m <---- f + // Or + // Case l1: m <----- f impossible. + // | + // l2: m + mln_assertion(!(d_ext.has(q) && fext(p) == fext(q) && d_ext.has(parent(q)) && q != parent(q))); + + while (d_ext.has(q) && !deja_vu(q) && (fext(q) != fext(parent(q)) || q == parent(q))) + { + s.append(q); + deja_vu(q) = true; + x = q; + q = parent(q); + } + + if (d_ext.has(q) && fext(q) == fext(parent(q)) && q != parent(q)) + { + q = (parent(x) = parent(q)); + mln_assertion(f.domain().has(q)); + } + + if (fext(q) == fext(parent(q))) + parent(x) = parent(q); + + s.append(p); + + mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q))); + } + + } + + std::cout << "Construction de l'arbre en " << tm << " s." << std::endl; + + data<I, S> tree(fext, parent, s); + + trace::exiting("mln::morpho::tree::impl::dual_hqueue"); + + return tree; + } + + } // end of namespace mln::morpho::tree::impl + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::tree + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif // !MLN_MORPHO_TREE_COMPUTE_PARENT_DUAL_HQUEUE_HH + + + Index: trunk/milena/sandbox/edwin/mln/morpho/tree/impl/union_find.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/impl/union_find.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/impl/union_find.hh (revision 4620) @@ -0,0 +1,172 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_MORPHO_TREE_IMPL_UNION_FIND_HH +# define MLN_MORPHO_TREE_IMPL_UNION_FIND_HH + +# include <mln/data/sort_psites.hh> +# include <mln/util/ctree/ctree.hh> + +namespace mln +{ + + namespace morpho + { + + namespace tree + { + + namespace impl + { + + template <typename T, typename I, typename N> + util::ctree::ctree<I> + union_find(const tag::tree::tree_t<T>&, + const Image<I>& f, + const Neighborhood<N>& nbh); + } + + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename I> + p_array<mln_psite(I)> + inline + sort_sites_set(const tag::tree::max_t&, const I& f) + { + p_array<mln_psite(I)> data = + data::sort_psites_increasing(f); + return data; + } + + template <typename I> + p_array<mln_psite(I)> + inline + sort_sites_set(const tag::tree::min_t&, const I& f) + { + p_array<mln_psite(I)> data = + data::sort_psites_decreasing(f); + return data; + } + + template <typename T> + inline + mln_psite(T) + zfind_root(T& zpar, const mln_psite(T)& x) + { + mlc_equal(mln_value(T), mln_psite(T))::check(); + if (zpar(x) == x) + return x; + else + return zpar(x) = zfind_root(zpar, zpar(x)); + } + + } + + + namespace impl + { + + namespace generic + { + + template <typename T, typename I, typename N> + util::ctree::ctree<I> + union_find(const tag::tree::tree_t<T>&, + const Image<I>& f_, + const Neighborhood<N>& nbh_) + { + trace::entering("morpho::tree::impl::generic::union_find"); + + typedef mln_psite(I) P; + typedef p_array<mln_psite(I)> S; + + const I& f = exact(f_); + const N& nbh = exact(nbh_); + S s = internal::sort_sites_set(T (), f); + + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, P) parent; + mln_ch_value(I, unsigned) area; + mln_ch_value(I, P) zpar; + unsigned nb_nodes = s.nsites(); + + initialize(deja_vu, f); + initialize(parent, f); + initialize(area, f); + initialize(zpar, f); + + // Initialization. + data::fill(deja_vu, false); + data::fill(area, 0); + + // Body. + mln_bkd_piter(S) p(s); // Backward. + mln_niter(N) n(nbh, p); + for_all(p) + { + // Make-Set. + parent(p) = p; + zpar(p) = p; + + for_all(n) + if (f.domain().has(n) && deja_vu(n)) + { + // Do-Union. + P r = internal::zfind_root(zpar, n); + if (r != p) + { + parent(r) = p; + zpar(r) = p; + area(p) += area(r); + if (f(r) != f(p)) + ++area(p); + else + --nb_nodes; + } + } + deja_vu(p) = true; + } + + util::ctree::ctree<I> tree(f, s, parent, area, nb_nodes); + + trace::exiting("morpho::tree::impl::generic::union_find"); + return tree; + } + + } + + } +# endif // ! MLN_INCLUDE_ONLY + } + + } + +} +#endif // !MLN_MORPHO_TREE_IMPL_UNION_FIND_HH Index: trunk/milena/sandbox/edwin/mln/morpho/tree/impl/dual_union_find.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/impl/dual_union_find.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/impl/dual_union_find.hh (revision 4620) @@ -0,0 +1,361 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH +# define MLN_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH + +/// +/// \brief The generic dual input tree algorithm for high quantized image. +/// +/// This implementation is based on tarjan's union method, so that +/// image quantization does not impact on the computation time. +/// +/// TODO: Think about how to extend f domain in a more +/// generic way. The actual implementation doubles the size of the +/// first dimension. It implies a boxed domain. +/// +/// TODO: Use the less functor. The actual implementation is for max-tree. + +# include <mln/data/fill.hh> + +# include <mln/geom/nsites.hh> +# include <mln/geom/translate.hh> + +# include <mln/morpho/tree/data.hh> + +# include <mln/util/timer.hh> + +namespace mln +{ + + namespace morpho + { + + namespace tree + { + + namespace impl + { + + namespace generic + { + + /// Compute a tree using union-find method. + /// + /// \param f The original image. + /// \param m The connectivity mask. + /// \param s_f The sorted site set of \p f + /// \param s_m The sorted site set of \p m. + /// \param nbh The neighborhood of the mask. + /// + /// \return The tree structure. + /// + template <typename I, typename S, typename N> + data< I, p_array<mln_psite(I)> > + dual_union_find(const Image<I>& f, + const Image<I>& m, + const Site_Set<S>& s_f, + const Site_Set<S>& s_m, + const Neighborhood<N>& nbh); + + } // end of namespace mln::morpho::tree::impl::generic + + } // end of namespace mln::morpho::tree::impl + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + // For benchmark purpose. More than 50% of the time is spent + // in find_root function. + static util::timer t_prop; + + + template <typename I> + inline + mln_psite(I) find_root(I& zpar, + const mln_psite(I)& p) + { + if (zpar(p) == p) + return p; + + t_prop.resume(); + mln_psite(I) x = zpar(p); + while (zpar(x) != x) + x = zpar(x); + + mln_psite(I) tmp; + for (mln_psite(I) y = p; y != x; y = tmp) + { + tmp = zpar(y); + zpar(y) = x; + } + t_prop.stop(); + + return x; + } + + template <typename I> + inline + void + update_m_parent(const I& f, + mln_ch_value(I, mln_psite(I))& parent, + mln_ch_value(I, bool)& deja_vu, + p_array< mln_psite(I) >& sset, + const mln_domain(I)& d_ext, + const mln_psite(I)& p) + { + typedef mln_psite(I) P; + + P q = parent(p); + P x = parent(q); + + mln_assertion(d_ext.has(q)); + + while (d_ext.has(x) && f(q) == f(x) && q != x) + { + q = x; + x = parent(q); + } + + if (!d_ext.has(x)) + { + if (f(x) == f(parent(x))) + x = (parent(q) = parent(x)); + if (f(q) != f(x)) + { + x = q; + if (!deja_vu(q)) + { + deja_vu(q) = true; + sset.append(q); + } + } + + } + else + { + if (x != q) + { + update_m_parent(f, parent, deja_vu, sset, d_ext, q); + x = q; + } + if (!deja_vu(q)) + { + deja_vu(q) = true; + sset.append(q); + } + } + + for (P i = p, tmp = parent(i); i != q; i = tmp, tmp = parent(i)) + parent(i) = x; + } + + } // end of namespace mln::morpho::tree::internal + + namespace impl + { + + namespace generic + { + + + template <typename I, typename S, typename N> + data< I, p_array<mln_psite(I)> > + dual_union_find(const Image<I>& f_, + const Image<I>& m_, + const Site_Set<S>& s_f_, + const Site_Set<S>& s_m_, + const Neighborhood<N>& nbh_) + { + trace::entering("morpho::tree::impl::generic::dual_union_find"); + + util::timer tm; + tm.start(); + internal::t_prop.reset(); + + typedef mln_psite(I) P; + typedef unsigned L; + + const I& f = exact(f_); + const I& m = exact(m_); + const S& s_f = exact(s_f_); + const S& s_m = exact(s_m_); + const N& nbh = exact(nbh_); + + // Aux data. + mln_psite(I)::delta dp(literal::zero); + mln_domain(I) d_f = f.domain(); + mln_domain(I) d_ext = f.domain(); // translate dp + mln_domain(I) d = f.domain(); + + // Extend the domain. + dp[0] = d.pmax()[0] - d.pmin()[0] + 1; + d.pmax() += dp; + d_ext.pmin() += dp; + d_ext.pmax() += dp; + + // Data. + mln_concrete(I) fext; + mln_ch_value(I, P) parent; + p_array<mln_psite(I)> s; + + // Initialization. + fext = geom::translate(m, dp.to_vec(), f, d); + initialize(parent, fext); + s.reserve(geom::nsites(fext)); + + //Process + { + // Aux data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, P) zpar; + + initialize(deja_vu, fext); + initialize(zpar, fext); + mln::data::fill(deja_vu, false); + + mln_bkd_piter(S) p_f(s_f); // Backward. + mln_bkd_piter(S) p_m(s_m); // Backward. + p_f.start(); + p_m.start(); + + // Main loop. + while (p_m.is_valid() || p_f.is_valid()) + { + mln_bkd_piter(S)& it = (!p_f.is_valid() || (p_m.is_valid() && f(p_f) <= m(p_m))) ? p_m : p_f; + + P p = it; + P ext = p + dp; + + // std::cout << "-------------------" << std::endl; + // std::cout << "Take " << p << " of value " << (&it == &p_m ? m(p) : f(p)) + // << " from " << (&it == &p_m ? "mask" : "f") << std::endl; + // debug::println("Parent: ", parent); + // debug::println("Zpar: ", zpar); + + mln_assertion(!(deja_vu(p) && deja_vu(ext))); + if (deja_vu(ext)) // Seen by mask before f. + { + mln_assertion(m(p) >= f(p)); + // Make set. + parent(p) = p; + zpar(p) = p; + + P r = internal::find_root(zpar, ext); + zpar(r) = p; + parent(r) = p; + + deja_vu(p) = true; + } + else if (deja_vu(p)) // Seen by f before mask. + { + mln_assertion(f(p) > m(p)); + parent(p) = ext; + zpar(p) = ext; + parent(ext) = ext; + zpar(ext) = ext; + + mln_niter(N) n(nbh, ext); + for_all(n) + if (d_ext.has(n) && deja_vu(n)) + { + P r = internal::find_root(zpar, n); + //std::cout << "Root: " << r << std::endl; + if (r != ext) + { + parent(r) = ext; + zpar(r) = ext; + } + } + deja_vu(ext) = true; + } + else if (f(p) <= m(p)) // First time p encountered. + { + zpar(ext) = ext; + mln_niter(N) n(nbh, ext); + for_all(n) + if (d_ext.has(n) && deja_vu(n)) + { + P r = internal::find_root(zpar, n); + if (r != ext) + { + zpar(r) = ext; + parent(r) = ext; + } + } + deja_vu(ext) = true; + } + else + { + deja_vu(p) = true; + } + it.next(); + } + } + std::cout << ">> MAJ zpar: " << internal::t_prop << " s" << std::endl; + std::cout << "Parent construction: " << tm << " s" << std::endl; + tm.restart(); + + // Canonization + { + mln_ch_value(I, bool) deja_vu(d_ext); + mln::data::fill(deja_vu, false); + mln_fwd_piter(S) p(s_f); // Forward. + for_all(p) + { + P q = parent(p); + if (!f.domain().has(q)) + internal::update_m_parent(fext, parent, deja_vu, s, d_ext, p); + else if (fext(parent(q)) == f(q)) + parent(p) = parent(q); + s.append(p); + + mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q))); + } + } + std::cout << "Canonization: " << tm << " s" << std::endl; + + //mln_postcondition(internal::compute_parent_postconditions(fext, s, parent)); + + tree::data<I, p_array<mln_psite(I)> > tree(fext, parent, s); + trace::exiting("morpho::tree::impl::generic::dual_union_find"); + + return tree; + } + + } // end of namespace mln::morpho::tree::impl::generic + + } // end of namespace mln::morpho::tree::impl + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::tree + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif // !MLN_MORPHO_TREE_IMLP_DUAL_UNION_FIND_HH Index: trunk/milena/sandbox/edwin/mln/morpho/tree/propagate_node.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/propagate_node.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/propagate_node.hh (revision 4620) @@ -0,0 +1,112 @@ +// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_MORPHO_TREE_PROPAGATE_NODE_HH +# define MLN_MORPHO_TREE_PROPAGATE_NODE_HH + +/// \file +/// +/// Functions to propagate node in the tree. +/// +/// \todo: The new implementation permits: + to propagate toward +/// subcomponents very fast (data::fill)\ + to propagate toward +/// supernodes as fast as the previous component\ + the attribute +/// image is still valid without the use of propagate_representative +/// that does not make sense any more. +/// +/// We are able in both cases to do something like: +/// + data::fill(attr_img | asc(n), v) +/// + data::fill(attr_img | desc(n), v) +/// +/// However the subimage morpher is not specialized for fast image and +/// does not take benefits in the fact that: +/// + desc(n) is a p_run (so can be memseté) +/// + attr_img can accessed by indexed (element() method for fast-image) + +# include <mln/core/image/attribute_image.hh> +# include <algorithm> + +namespace mln +{ + + namespace morpho + { + + namespace tree + { + + template <typename T, typename V> + inline + unsigned + propagate_node_to_descendants(attribute_image<T, V>& a, + const typename T::node_t& n, + const V& value) + { + typedef typename T::nodes_t desc_t; + mln_precondition(a.is_valid()); + mln_precondition(a.has(n)); + + // (n € desc(n)) but we don't set its value. + unsigned i = a.tree().desc(n).nsites(); + + if (i > 0) + { + mln_assertion(a.tree().has_index(n.index() + i)); + V* v = a.buffer() + n.index(); + std::fill(v + 1, v + i, value); + } + return i - 1; + } + + template <typename T, typename V> + inline + unsigned + propagate_node_to_ancestors(attribute_image<T, V>& a, + typename T::node_t n, + const V& v) + { + mln_precondition(a.is_valid()); + mln_precondition(a.has(n)); + + if (a.tree().is_a_root(n)) + return 0; + + unsigned i = 0; + do { + n = a.tree().parent(n); + a(n) = v; + ++i; + } while (!a.tree().is_a_root(n)); + + return i; + } + + } // end of namespace mln::morpho::tree + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif // ! MLN_MORPHO_TREE_PROPAGATE_NODE_HH Index: trunk/milena/sandbox/edwin/mln/debug/ctree.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/debug/ctree.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/debug/ctree.hh (revision 4620) @@ -0,0 +1,155 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_DEBUG_CTREE_HH +# define MLN_DEBUG_CTREE_HH + +# include <mln/util/ctree/ctree.hh> +# include <mln/core/image/attribute_image.hh> +# include <mln/core/site_set/p_array.hh> +# include <mln/math/max.hh> +# include <vector> +# include <iostream> + + +namespace mln +{ + + namespace debug + { + + /// \brief Print a morphological tree. + /// + /// \param[in] tree The tree to be print. + /// + template <typename T> + void + println(const Tree<T>& tree); + + /// \brief Print an attribute image. + /// + /// \param[in] a The attribute image. + /// + template <typename T, typename V> + void + println(const attribute_image<T, V>& a); + + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename T, typename V> + void + println(const T& tree, const std::vector<V>& values) + { + typedef std::vector< p_array<mln_psite(T)> > hset_t; + hset_t hset(tree.nodes().nsites()); + + // Make site set of each node. + { + mln_piter(T::domain_t) p(tree.domain()); + for_all(p) + hset[tree.node(p).index()].insert(p); + } + + // Retrieve the height + unsigned height = 0; + { + attribute_image<T, unsigned> h(tree); + data::fill(h, 0); + + mln_bkd_piter(T::nodes_t) n(tree.nodes()); + for_all(n) + if (!tree.is_a_root(n)) + h(tree.parent(n)) = math::max(h(tree.parent(n)), h(n) + 1); + else + height = math::max(height, h(n)); + } + { + std::cout << "Node"; + for (unsigned i = 0; i < height; i++) + std::cout << " "; + std::cout << "Value\tSites" << std::endl; + } + + mln_fwd_piter(T::nodes_t) n(tree.nodes()); + typename T::node_t old; + unsigned depth = 0; + for_all(n) + { + if (tree.is_a_root(n)) + depth = 0; + else + { + while (old != tree.parent(n)) + { + --depth; + old = tree.parent(old); + } + ++depth; + } + + for (unsigned i = 0; i < depth; i++) + std::cout << " "; + std::cout << n; + for (unsigned i = depth; i < height + 1; i++) + std::cout << " "; + + old = n; + std::cout << values[old.index()] << "\t" + << hset[old.index()] << std::endl; + } + + } + + } // end of namespace mln::debug::internal + + template <typename T> + void + println(const Tree<T>& tree_) + { + const T& tree = exact(tree_); + + mln_precondition(tree.is_valid()); + internal::println(tree, tree.data_hook_()->values_); + } + + template <typename T, typename V> + void + println(const attribute_image<T, V>& a) + { + mln_precondition(a.is_valid()); + internal::println(a.tree(), a.hook_data_()->values_); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::debug + +} // end of namespace mln + +#endif // !MLN_DEBUG_CTREE_HH Index: trunk/milena/sandbox/edwin/mln/core/site_set/p_run_idx.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/site_set/p_run_idx.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/site_set/p_run_idx.hh (revision 4620) @@ -0,0 +1,458 @@ +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CORE_SITE_SET_P_RUN_IDX_HH +# define MLN_CORE_SITE_SET_P_RUN_IDX_HH + +/// \file +/// +/// Definition of a run of index sites. +/// +/// \todo Use a lazy approach (in subj) like in p_array psite. +/// +/// FIXME: Wanted to have: +/// p_run_idx_psite < internal::index_site_base +/// < internal::pseudo_site_base +/// but diamond inheritance doesn't work even with virtual keyword... + +# include <mln/core/internal/index_site_base.hh> +# include <mln/core/internal/site_set_base.hh> +# include <mln/core/internal/pseudo_site_base.hh> +# include <mln/util/index.hh> + + +namespace mln +{ + + // Forward declarations. + template <typename P> class p_run_idx; + template <typename P> class p_run_idx_psite; + template <typename P> class p_run_idx_fwd_piter_; + template <typename P> class p_run_idx_bkd_piter_; + + namespace trait + { + + template <typename P> + struct site_set_< p_run_idx<P> > + { + typedef trait::site_set::nsites::known nsites; + typedef trait::site_set::bbox::unknown bbox; + typedef trait::site_set::contents::fixed contents; + typedef trait::site_set::arity::unique arity; + }; + + template <typename P> + struct set_precise_unary_< op::ord, p_run_idx<P> > + { + typedef set_precise_unary_< op::ord, p_run_idx<P> > ret; // Itself. + bool strict(const p_run_idx<P>& lhs, const p_run_idx<P>& rhs) const; + }; + + } // end of namespace trait + + + + /// \brief Site set class in run. + /// + /// \ingroup modsitesetbasic + template <typename P> + class p_run_idx : public internal::site_set_base_< P, p_run_idx<P> > + { + public: + + /// Element associated type. + typedef P element; + + /// Psite associated type. + typedef p_run_idx_psite<P> psite; + + /// Forward Site_Iterator associated type. + typedef p_run_idx_fwd_piter_<P> fwd_piter; + + /// Backward Site_Iterator associated type. + typedef p_run_idx_bkd_piter_<P> bkd_piter; + + /// Site_Iterator associated type. + typedef fwd_piter piter; + + + /// Constructor without argument. + p_run_idx(); + + /// Constructor. + p_run_idx(const P& start, const mln_delta(P)& len); + + /// Constructor. + p_run_idx(const P& start, const P& end); + + /// Init + void init(const P& start, const mln_delta(P)& len); + + /// Constructor. + void init(const P& start, const P& end); + + /// Test if \p p belongs to this site set. + bool has(const psite& p) const; + + /// Test if \p p belongs to this site set. + bool has(const P& p) const; + + /// Test if index \p i belongs to this site set. + bool has_index(unsigned i) const; + + /// Give the number of sites. + unsigned nsites() const; + + /// Return the \p i-th site. + P operator[](int i) const; + + /// Return the starting site. + const P& start() const; + + /// Return (compute) the ending site. + P end() const; + + /// Test if this run is valid, i.e., with length > 0. + bool is_valid() const; + + /// Return the size of this site set in memory. + std::size_t memory_size() const; + + protected: + + /// The first site of the run. + P start_; + + /// The length of the run. + mln_delta(P) len_; + }; + + + template <typename P> + std::ostream& operator<<(std::ostream& ostr, const p_run_idx<P>& r); + + template <typename P> + class p_run_idx_psite : public internal::pseudo_site_base_< const P&, p_run_idx_psite<P> > + { + typedef p_run_idx_psite<P> self; + typedef internal::pseudo_site_base_<const P&, self> super; + + public: + + // This associated type is important to know that this particular + // pseudo site knows the site set it refers to. + typedef p_run_idx<P> target; + + // As a Proxy: + const P& subj_(); + + p_run_idx_psite(); + p_run_idx_psite(const p_run_idx<P>& run, int i); + + int index() const; + void change_index(int i); + void inc_index(); + void dec_index(); + + const p_run_idx<P>* target_() const; + void change_target(const p_run_idx<P>& new_target); + + bool is_valid() const; + + operator util::index() const; + + const p_run_idx<P>& run() const; + + private: + + const p_run_idx<P>* run_; + int i_; + mutable P p_; + }; + + +# ifndef MLN_INCLUDE_ONLY + + template <typename P> + inline + p_run_idx<P>::p_run_idx() + { + len_.change_value(0); + } + + template <typename P> + inline + p_run_idx<P>::p_run_idx(const P& start, const mln_delta(P)& len) + { + mln_precondition(len.value() != 0); + init(start, len); + } + + + template <typename P> + inline + void + p_run_idx<P>::init(const P& start, const mln_delta(P)& len) + { + mln_precondition(len.value() != 0); + start_ = start; + len_ = len; + } + + template <typename P> + inline + p_run_idx<P>::p_run_idx(const P& start, const P& end) + { + mln_precondition(start <= end); + init(start, end - start + 1); + } + + template <typename P> + inline + void + p_run_idx<P>::init(const P& start, const P& end) + { + mln_precondition(start <= end); + init(start, end - start + 1); + } + + template <typename P> + inline + bool + p_run_idx<P>::is_valid() const + { + return len_.value() != 0; + } + + template <typename P> + inline + bool + p_run_idx<P>::has(const psite& p) const + { + mln_precondition(p.target_() == this); // FIXME: Refine. + if (p.index() >= len_.value()) + return false; + // The type of rhs below is mln_site(p_run_idx<P>). + mln_invariant(p.to_site() == (*this)[p.index()]); + return true; + } + + template <typename P> + inline + bool + p_run_idx<P>::has(const P& p) const + { + mln_precondition(is_valid()); + return start_ <= p && p <= end(); + } + + template <typename P> + inline + bool + p_run_idx<P>::has_index(unsigned i) const + { + return i < len_.value(); + } + + template <typename P> + inline + unsigned + p_run_idx<P>::nsites() const + { + mln_precondition(is_valid()); + return len_.value(); + } + + template <typename P> + inline + P + p_run_idx<P>::operator[](int i) const + { + mln_precondition(is_valid()); + mln_precondition(i >= 0); + mln_precondition(i < len_.value()); + P p = start_ + (mln_delta(P))i; + return p; + } + + template <typename P> + inline + const P& + p_run_idx<P>::start() const + { + return start_; + } + + template <typename P> + inline + P + p_run_idx<P>::end() const + { + P p = start_ + (len_ - 1); + return p; + } + + template <typename P> + inline + std::size_t + p_run_idx<P>::memory_size() const + { + return sizeof(*this); + } + + template <typename P> + std::ostream& operator<<(std::ostream& ostr, const p_run_idx<P>& r) + { + ostr << '(' << r.start() << ", " << r.nsites() << ')'; + return ostr; + } + + // p_run_idx_psite<P> + + template <typename P> + inline + p_run_idx_psite<P>::p_run_idx_psite() + : run_(0), + i_(0) + { + } + + template <typename P> + inline + p_run_idx_psite<P>::p_run_idx_psite(const p_run_idx<P>& run, int i) + : run_(&run), + i_(i), + p_(run.start()) + { + p_ += i_; + } + + template <typename P> + inline + bool + p_run_idx_psite<P>::is_valid() const + { + return run_ != 0 && run_->has_index(i_); + } + + template <typename P> + inline + int + p_run_idx_psite<P>::index() const + { + return i_; + } + + template <typename P> + inline + void + p_run_idx_psite<P>::change_index(int i) + { + p_ += (mln_delta(P))(i - i_); + i_ = i; + } + + template <typename P> + inline + void + p_run_idx_psite<P>::dec_index() + { + --i_; + p_.dec_index(); + } + + template <typename P> + inline + void + p_run_idx_psite<P>::inc_index() + { + ++i_; + p_.inc_index(); + } + + template <typename P> + inline + const p_run_idx<P>* + p_run_idx_psite<P>::target_() const + { + return run_; + } + + template <typename P> + inline + void + p_run_idx_psite<P>::change_target(const p_run_idx<P>& new_target) + { + run_ = & new_target; + i_ = 0; + p_ = run_->start(); + } + + template <typename P> + inline + const P& + p_run_idx_psite<P>::subj_() + { + return p_; + } + + template <typename P> + inline + p_run_idx_psite<P>::operator util::index() const + { + return i_; + } + + template <typename P> + inline + const p_run_idx<P>& + p_run_idx_psite<P>::run() const + { + mln_precondition(run_ != 0); + return *run_; + } + namespace trait + { + + template <typename P> + inline + bool + set_precise_unary_< op::ord, p_run_idx<P> >::strict(const p_run_idx<P>& lhs, const p_run_idx<P>& rhs) const + { + return util::ord_strict(lhs.start(), rhs.start()); + } + + } // end of namespace trait + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + +# include <mln/core/site_set/p_run_idx_piter.hh> + + +#endif // ! MLN_CORE_SITE_SET_P_RUN_IDX_HH Index: trunk/milena/sandbox/edwin/mln/core/site_set/p_run_idx_piter.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/site_set/p_run_idx_piter.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/site_set/p_run_idx_piter.hh (revision 4620) @@ -0,0 +1,222 @@ +// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CORE_SITE_SET_P_RUN_IDX_PITER_HH +# define MLN_CORE_SITE_SET_P_RUN_IDX_PITER_HH + +/*! \file + * + * \brief Definition of point iterators on mln::p_run_idx. + */ + +# include <mln/core/site_set/p_run_idx.hh> +# include <mln/core/internal/site_set_iterator_base.hh> + + +namespace mln +{ + + /*! \brief Forward iterator on points of a p_run_idx<P>. + * + */ + template <typename P> + class p_run_idx_fwd_piter_ + : + public internal::site_set_iterator_base< p_run_idx<P>, + p_run_idx_fwd_piter_<P> > + { + typedef p_run_idx_fwd_piter_<P> self_; + typedef internal::site_set_iterator_base< p_run_idx<P>, self_ > super_; + public: + + /// Constructor without arguments. + p_run_idx_fwd_piter_(); + + /// Coordinate associated type. + p_run_idx_fwd_piter_(const p_run_idx<P>& r); + + /// Test if the iterator is valid. + bool is_valid_() const; + + /// Invalidate the iterator. + void invalidate_(); + + /// Start an iteration. + void start_(); + + /// Go to the next point. + void next_(); + + protected: + using super_::p_; + using super_::s_; + }; + + + + /*! \brief Backward iterator on points of a p_run_idx<P>. + * + */ + template <typename P> + class p_run_idx_bkd_piter_ + : + public internal::site_set_iterator_base< p_run_idx<P>, + p_run_idx_bkd_piter_<P> > + { + typedef p_run_idx_bkd_piter_<P> self_; + typedef internal::site_set_iterator_base< p_run_idx<P>, self_ > super_; + public: + + /// Constructor without arguments. + p_run_idx_bkd_piter_(); + + /// Coordinate associated type. + p_run_idx_bkd_piter_(const p_run_idx<P>& r); + + /// Test if the iterator is valid. + bool is_valid_() const; + + /// Invalidate the iterator. + void invalidate_(); + + /// Start an iteration. + void start_(); + + /// Go to the next point. + void next_(); + + protected: + using super_::p_; + using super_::s_; + }; + + + +# ifndef MLN_INCLUDE_ONLY + + // p_run_idx_fwd_piter_<P> + + template <typename P> + inline + p_run_idx_fwd_piter_<P>::p_run_idx_fwd_piter_() + { + } + + template <typename P> + inline + p_run_idx_fwd_piter_<P>::p_run_idx_fwd_piter_(const p_run_idx<P>& r) + { + this->change_target(r); + } + + template <typename P> + inline + bool + p_run_idx_fwd_piter_<P>::is_valid_() const + { + mln_invariant(p_.index() >= 0); + return p_.index() < int(s_->nsites()); + } + + template <typename P> + inline + void + p_run_idx_fwd_piter_<P>::invalidate_() + { + p_.change_index(s_->nsites()); + } + + template <typename P> + inline + void + p_run_idx_fwd_piter_<P>::start_() + { + p_.change_index(0); + } + + template <typename P> + inline + void + p_run_idx_fwd_piter_<P>::next_() + { + p_.inc_index(); + } + + + // p_run_idx_bkd_piter_<P> + + template <typename P> + inline + p_run_idx_bkd_piter_<P>::p_run_idx_bkd_piter_() + { + } + + template <typename P> + inline + p_run_idx_bkd_piter_<P>::p_run_idx_bkd_piter_(const p_run_idx<P>& r) + { + this->change_target(r); + } + + template <typename P> + inline + bool + p_run_idx_bkd_piter_<P>::is_valid_() const + { + mln_invariant(p_.index() < int(s_->nsites())); + return p_.index() >= 0; + } + + template <typename P> + inline + void + p_run_idx_bkd_piter_<P>::invalidate_() + { + p_.change_index(-1); + } + + template <typename P> + inline + void + p_run_idx_bkd_piter_<P>::start_() + { + p_.change_index(s_->nsites() - 1); + } + + template <typename P> + inline + void + p_run_idx_bkd_piter_<P>::next_() + { + p_.dec_index(); + } + + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + +#endif // ! MLN_CORE_SITE_SET_P_RUN_IDX_PITER_HH Index: trunk/milena/sandbox/edwin/mln/core/image/attribute_image.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/image/attribute_image.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/image/attribute_image.hh (revision 4620) @@ -0,0 +1,435 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CORE_IMAGE_ATTRIBUTE_IMAGE_HH +# define MLN_CORE_IMAGE_ATTRIBUTE_IMAGE_HH + +# include <mln/core/internal/image_primary.hh> +# include <mln/core/concept/tree.hh> +# include <mln/metal/converts_to.hh> + +namespace mln +{ + // Forward declaration. + template <typename T, typename V> class attribute_image; + + namespace internal + { + + /// Data structure for \c mln::attribute_image + template <typename T, typename V> + struct data< mln::attribute_image<T, V> > + { + data(); + data(const T& tree); + ~data(); + + std::vector<V> values_; + T tree_; // An attribute image can hold the tracked-data of the tree. + }; + + } // end of namespace mln::internal + + namespace trait + { + + template <typename T, typename V> + struct image_< attribute_image<T, V> > : default_image_< V, attribute_image<T, V> > + { + // misc + typedef trait::image::category::primary category; + typedef trait::image::speed::fastest speed; + typedef trait::image::size::regular size; + + // value + typedef trait::image::vw_io::none vw_io; + typedef trait::image::vw_set::none vw_set; + typedef trait::image::value_access::direct value_access; + typedef trait::image::value_alignment::irrelevant value_alignment; + typedef trait::image::value_browsing::site_wise_only value_browsing; + typedef trait::image::value_storage::one_block value_storage; + typedef trait::image::value_io::read_write value_io; + + // site / domain + typedef trait::image::pw_io::read_write pw_io; + typedef trait::image::localization::none localization; + typedef trait::image::dimension::none dimension; + + // extended domain + typedef trait::image::ext_domain::none ext_domain; + typedef trait::image::ext_value::irrelevant ext_value; + typedef trait::image::ext_io::irrelevant ext_io; + }; + + } // end of namespace mln::trait + + + namespace convert + { + + namespace over_load + { + + template <typename T, typename V, typename I> + void + from_to_(const mln::attribute_image<T, V>& from, Image<I>& to_) + { + typedef mln::attribute_image<T, V> A; + I& to = exact(to_); + + mlc_converts_to(V, mln_value(I))::check(); + mlc_converts_to(typename T::domain_t, mln_domain(I))::check(); + + mln_precondition(from.is_valid()); + to.init_(from.tree().domain()); + + mln_fwd_piter(I) p(to.domain()); + for_all(p) + convert::from_to(from(from.tree().node(p)), to(p)); + } + + } // enf of namespace mln::convert::over_load + + } // end of namespace mln::convert + + + /// Basic attribute image class. + /// + /// The parameter \c V is the type of pixel values (usually the + /// result type of the attribute). This image class stores data in + /// memory. + /// + /// \ingroup modimageconcrete + // + template <typename T, typename V> + class attribute_image : public internal::image_primary< V, typename T::nodes_t, attribute_image<T, V> > + { + typedef internal::image_primary< V, typename T::nodes_t, attribute_image<T, V> > super_; + typedef attribute_image<T, V> self_; + + public: + + /// Value associated type. + typedef V value; + /// Return type of read-only access. + typedef const V& rvalue; + /// Return type of read-write access. + typedef V& lvalue; + + + /// Site (node) assocatied type. + typedef typename T::node_t node_t; + typedef node_t site; + typedef node_t psite; + + /// Site set (node set) associated type. + typedef typename T::nodes_t nodes_t; + + /// Skeleton. + typedef attribute_image< T, tag::value_<V> > skeleton; + + /// Constructors + /// \{ + /// Constructor without argument. + attribute_image(); + /// Allocate an attribute image respecting the size of the tree. + attribute_image(const Tree<T>& tree); + /// \} + + /// Initialize an empty image. + void init_(const Tree<T>& tree); + + /// Test if the node \p n is valid. + bool has(const node_t& n) const; + + /// Give the node site set. + const nodes_t& domain() const; + + /// Read-only access to the image value at node \p n. + rvalue operator()(const node_t& n) const; + + /// Read-write access to the image value at node \p n. + lvalue operator()(const node_t& n); + + // Specific methods: + // ---------------- + + /// Read access to the value at point \p p. + /// Note: can be ambigous if the node content is a node set. + rvalue operator()(const mln_psite(T)& p) const; + + /// Return the tree. + const T& tree() const; + + /// Change the target tree. + void change_tree(const Tree<T>& tree); + + // As a fastest image. + // ------------------ + + /// Give the number of elements. + unsigned nelements() const; + + /// Read-only access to the image value lacated at index \p i. + rvalue element(unsigned i) const; + + /// Read-write access to the image value lacated at index \p i. + lvalue element(unsigned i); + + /// Return the border. (Required by image fastest / return always 0). + unsigned border() const; + + /// Give the delta_index corresponding to the delta point. + int delta_index(const mln_delta(node_t)& dp) const; + + /// Give the point corresponding to the index \p i; + node_t point_at_index(unsigned i) const; + + /// Give a hook to the value buffer. + const value* buffer() const; + + /// Give a hook to the value buffer. + value* buffer(); + }; + + // Forward declaration. + template <typename T, typename V, typename V2> + void init_(tag::image_t, mln::attribute_image<T, V>& target, const mln::attribute_image<T, V2>& model); + + +# ifndef MLN_INCLUDE_ONLY + + // init_ + + template <typename T, typename V, typename V2> + inline + void + init_(tag::image_t, mln::attribute_image<T, V>& target, const mln::attribute_image<T, V2>& model) + { + target.init_(model.tree()); + } + + // internal::data + + namespace internal + { + + template <typename T, typename V> + inline + data< attribute_image<T, V> >::data() + { + } + + template <typename T, typename V> + inline + data< attribute_image<T, V> >::data(const T& tree) + : values_ (tree.n_nodes()), + tree_ (tree) + { + } + + template <typename T, typename V> + inline + data< attribute_image<T, V> >::~data() + { + } + + } // end of namespace mln::internal + + + template <typename T, typename V> + inline + attribute_image<T, V>::attribute_image() + { + } + + + template <typename T, typename V> + inline + attribute_image<T, V>::attribute_image(const Tree<T>& tree_) + { + const T& tree = exact(tree_); + mln_precondition(tree.is_valid()); + this->data_ = new internal::data< self_ >(tree); + } + + template <typename T, typename V> + inline + unsigned + attribute_image<T, V>::border() const + { + return 0; + } + + template <typename T, typename V> + inline + void + attribute_image<T, V>::init_(const Tree<T>& tree_) + { + const T& tree = exact(tree_); + mln_precondition(tree.is_valid()); + this->data_->tree_ = tree; + this->data_->values_.resize(tree.n_nodes()); + } + + template <typename T, typename V> + inline + bool + attribute_image<T, V>::has(const node_t& n) const + { + mln_precondition(this->is_valid()); + return this->domain().has(n); + } + + template <typename T, typename V> + inline + const typename T::nodes_t& + attribute_image<T, V>::domain() const + { + mln_precondition(this->is_valid()); + return this->data_->tree_.nodes(); + } + + template <typename T, typename V> + inline + const V& + attribute_image<T, V>::operator()(const node_t& n) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + return this->data_->values_[n.index()]; + } + + template <typename T, typename V> + inline + V& + attribute_image<T, V>::operator()(const node_t& n) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + return this->data_->values_[n.index()]; + } + + // Specific methods: + // ---------------- + + + template <typename T, typename V> + inline + const V& + attribute_image<T, V>::operator()(const mln_psite(T)& p) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->tree_.has(p)); + return this->data_->values_[this->data_->tree_.node_at_(p)]; + } + + template <typename T, typename V> + inline + const T& + attribute_image<T, V>::tree() const + { + mln_precondition(this->is_valid()); + return this->data_->tree_; + } + + template <typename T, typename V> + inline + void + attribute_image<T, V>::change_tree(const Tree<T>& tree_) + { + const T& tree = exact(tree_); + mln_precondition(tree.is_valid()); + this->data_->tree_ = tree; + } + + template <typename T, typename V> + inline + unsigned + attribute_image<T, V>::nelements() const + { + mln_precondition(this->is_valid()); + return this->domain().nsites(); + } + + template <typename T, typename V> + inline + const V& + attribute_image<T, V>::element(unsigned i) const + { + mln_precondition(this->is_valid()); + mln_precondition(i < this->nelements()); + return this->data_->values_[i]; + } + + template <typename T, typename V> + inline + V& + attribute_image<T, V>::element(unsigned i) + { + mln_precondition(this->is_valid()); + mln_precondition(i < this->nelements()); + return this->data_->values_[i]; + } + + template <typename T, typename V> + inline + int + attribute_image<T, V>::delta_index(const mln_delta(node_t)& dp) const + { + mln_precondition(this->is_valid()); + return dp.value(); + } + + template <typename T, typename V> + inline + typename T::node_t + attribute_image<T, V>::point_at_index(unsigned i) const + { + mln_precondition(this->is_valid()); + node_t tmp(this->data_->tree_, i); + return tmp; + } + + template <typename T, typename V> + inline + const V* + attribute_image<T, V>::buffer() const + { + return &(this->data_->values_[0]); + } + + template <typename T, typename V> + inline + V* attribute_image<T, V>::buffer() + { + return &(this->data_->values_[0]); + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_CORE_IMAGE_ATTRIBUTE_IMAGE_HH Index: trunk/milena/sandbox/edwin/mln/core/concept/index_site.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/concept/index_site.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/concept/index_site.hh (revision 4620) @@ -0,0 +1,311 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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. + +/// +/// \brief Definition of the concept mln::index_site. +/// +/// FIXME: doc! +/// + + +#ifndef MLN_CORE_CONCEPT_INDEX_SITE_HH +# define MLN_CORE_CONCEPT_INDEX_SITE_HH + +# include <mln/core/concept/site.hh> +# include <mln/value/concept/integer.hh> +# include <mln/core/concept/dindex_site.hh> + + +namespace mln +{ + // Forward declaration. + template <typename E> struct Index_Site; + + namespace trait + { + + template < typename P, typename D > + struct set_binary_< op::plus, + mln::Index_Site, P, mln::Dindex_Site, D > + { + typedef P ret; + }; + + template < typename P, typename D > + struct set_binary_< op::minus, + mln::Index_Site, P, mln::Dindex_Site, D > + { + typedef P ret; + }; + + template < typename L, typename R > + struct set_binary_< op::minus, + mln::Index_Site, L, mln::Index_Site, R > + { + typedef mln_delta(L) ret; + }; + + template < typename L, typename R > + struct set_binary_< op::times, + mln::Index_Site, L, + mln::Object, mln::value::scalar_<R> > + { + typedef L ret; + }; + + template < typename L, typename R > + struct set_binary_< op::div, + mln::Index_Site, L, + mln::Object, mln::value::scalar_<R> > + { + typedef L ret; + }; + + template <typename P> + struct set_unary_< op::ord, mln::Index_Site, P > + { + typedef mln::internal::ord_less< P > ret; + }; + + } + + // Index Site category flag type. + template <> + struct Index_Site<void> + { + typedef Site<void> super; + }; + + template <typename E> + struct Index_Site : public Site<E> + { + typedef Index_Site<void> category; + + /* + typedef delta; + typedef index_t; + + const index_t& index() const; + void change_index(const index_t&); + + void dec_index(); + void inc_index(); + + */ + + protected: + Index_Site(); + }; + + // Conversion. + + namespace convert + { + + namespace over_load + { + + template <typename P> + void + from_to_(const Index_Site<P>& from, mln_delta(P)& to); + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + + /// Operators. + /// \{ + template <typename P> + std::ostream& + operator<<(std::ostream& ostr, const Index_Site<P>& dp); + + template <typename L, typename R> + bool operator==(const Index_Site<L>& lhs, const Index_Site<R>& rhs); + + template <typename L, typename R> + bool operator<(const Index_Site<L>& lhs, const Index_Site<R>& rhs); + + template <typename P, typename D> + P operator+(const Index_Site<P>& p, const Dindex_Site<D>& dp); + + template <typename P, typename D> + P operator-(const Index_Site<P>& p, const Dindex_Site<D>& dp); + + template <typename P, typename S> + P operator*(const Index_Site<P>& p, const value::scalar_<S>& s); + + template <typename P, typename S> + P operator/(const Index_Site<P>& p, const value::scalar_<S>& s); + + template <typename L, typename R> + mln_delta(L) operator-(const Index_Site<L>& lhs, const Index_Site<R>& rhs); + + template <typename P, typename D> + P& operator+=(Index_Site<P>& p, const Dindex_Site<D>& dp); + + template <typename P, typename D> + P& operator-=(Index_Site<P>& p, const Dindex_Site<D>& dp); + + template <typename P, typename S> + P& operator*=(Index_Site<P>& p, const value::scalar_<S>& s); + + template <typename P, typename S> + P& operator/=(Index_Site<P>& p, const value::scalar_<S>& s); + + /// \} + +# ifndef MLN_INCLUDE_ONLY + + template <typename E> + inline + Index_Site<E>::Index_Site() + { + typedef mln_delta(E) delta; + typedef typename E::index_t index_t; + + void (E::*m1)() = & E::inc_index; + m1 = 0; + void (E::*m2)() = & E::dec_index; + m2 = 0; + const index_t& (E::*m3)() const = & E::index; + m3 = 0; + void (E::*m4)(const index_t&) = & E::change_index; + m4 = 0; + } + + namespace convert + { + + namespace over_load + { + + template <typename P> + void + from_to_(const Index_Site<P>& from, mln_delta(P)& to) + { + to.value() = exact(from).index(); + } + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + template <typename P> + std::ostream& + operator<<(std::ostream& ostr, const Index_Site<P>& p) + { + ostr << '(' << debug::format(exact(p).index()) << ')'; + return ostr; + } + + template <typename L, typename R> + bool operator==(const Index_Site<L>& lhs, const Index_Site<R>& rhs) + { + return exact(lhs).index() == exact(rhs).index(); + } + + template <typename L, typename R> + bool operator<(const Index_Site<L>& lhs, const Index_Site<R>& rhs) + { + return exact(lhs).index() < exact(rhs).index(); + } + + template <typename P, typename D> + P operator+(const Index_Site<P>& p, const Dindex_Site<D>& dp) + { + P tmp = exact(p); + tmp.change_index(tmp.index() + exact(dp).value()); + return tmp; + } + + template <typename P, typename D> + P operator-(const Index_Site<P>& p, const Dindex_Site<D>& dp) + { + P tmp = exact(p); + tmp.change_index(tmp.index() - exact(dp).value()); + return tmp; + } + + template <typename P, typename S> + P operator*(const Index_Site<P>& p, const value::scalar_<S>& s) + { + S equiv = s.to_equiv(); + P tmp = exact(p); + tmp.change_index(tmp.index() * equiv); + return tmp; + } + + + template <typename P, typename S> + P operator/(const Index_Site<P>& p, const value::scalar_<S>& s) + { + S equiv = s.to_equiv(); + P tmp = exact(p); + tmp.change_index(tmp.index() / equiv); + return tmp; + } + + + template <typename L, typename R> + mln_delta(L) operator-(const Index_Site<L>& lhs, const Index_Site<R>& rhs) + { + mln_delta(L) delta(exact(lhs).index() - exact(rhs).index()); + mln_postcondition(rhs + delta == lhs); + return delta; + } + + template <typename P, typename D> + P& operator+=(Index_Site<P>& p, const Dindex_Site<D>& dp) + { + exact(p).change_index(exact(p).index() + exact(dp).value()); + return exact(p); + } + + template <typename P, typename D> + P& operator-=(Index_Site<P>& p, const Dindex_Site<D>& dp) + { + exact(p).change_index(exact(p).index() - exact(dp).value()); + return exact(p); + } + + template <typename P, typename S> + P& operator*=(Index_Site<P>& p, const value::scalar_<S>& s) + { + exact(p).change_index(exact(p).index() * s); + return exact(p); + } + + template <typename P, typename S> + P& operator/=(Index_Site<P>& p, const value::scalar_<S>& s) + { + exact(p).change_index(exact(p).index() / s); + return exact(p); + } +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_CORE_CONCEPT_INDEX_SITE_HH Index: trunk/milena/sandbox/edwin/mln/core/concept/dindex_site.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/concept/dindex_site.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/concept/dindex_site.hh (revision 4620) @@ -0,0 +1,253 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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. + +/// +/// \file +/// +/// Definition of the concept mln::Dindex_Site +/// + +#ifndef MLN_CORE_CONCEPT_DINDEX_SITE_HH +# define MLN_CORE_CONCEPT_DINDEX_SITE_HH + +namespace mln +{ + + // Forward declaration. + template <typename E> struct Dindex_Site; + + + namespace trait + { + + // FIXME: Add promotion. + + template < typename L, typename R > + struct set_binary_< op::plus, + mln::Dindex_Site, L, mln::Dindex_Site, R > + { + typedef L ret; + }; + + template < typename L, typename R > + struct set_binary_< op::minus, + mln::Dindex_Site, L, mln::Dindex_Site, R > + { + typedef L ret; + }; + + template < typename L, typename S> + struct set_binary_< op::plus, + mln::Dindex_Site, L, mln::value::Scalar, S > + { + typedef L ret; + }; + + template < typename L, typename S> + struct set_binary_< op::minus, + mln::Dindex_Site, L, mln::value::Scalar, S > + { + typedef L ret; + }; + + template < typename D, typename S > + struct set_binary_< op::times, + mln::Dindex_Site, D, + mln::value::Scalar, S > + { + typedef D ret; + }; + + template <typename D> + struct set_unary_< op::ord, mln::Dindex_Site, D > + { + typedef mln::internal::ord_less< D > ret; + }; + + } // end of namespace mln::trait + + + + /// Delta point site category flag type. + template <> + struct Dindex_Site<void> + { + typedef Object<void> super; + }; + + + /// FIXME: Doc! + template <typename E> + struct Dindex_Site : public Object<E> + { + typedef Dindex_Site<void> category; + + /* + typedef value_t; + typedef site; + typedef psite; + + const value_t& value(); + void change_value(const value_t&); + */ + + protected: + Dindex_Site(); + }; + + + + // Operators. + + template <typename D> + std::ostream& + operator<<(std::ostream& ostr, const Dindex_Site<D>& dp); + + template <typename L, typename R> + bool + operator==(const Dindex_Site<L>& lhs, const Dindex_Site<R>& rhs); + + + template <typename L, typename R> + L operator+(const Dindex_Site<L>& lhs, const Dindex_Site<R>& rhs); + + template <typename L, typename R> + L operator-(const Dindex_Site<L>& lhs, const Dindex_Site<R>& rhs); + + template <typename L, typename S> + L operator+(const Dindex_Site<L>& lhs, const value::Scalar<S>& rhs); + + template <typename L, typename S> + L operator-(const Dindex_Site<L>& lhs, const value::Scalar<S>& rhs); + + template <typename D, typename S> + D operator*(const Dindex_Site<D>& lhs, const value::Scalar<S>& rhs); + + + namespace convert + { + + namespace over_load + { + + template <typename D> + void + from_to_(const Dindex_Site<D>& from, mln_site(D)& to); + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + + +# ifndef MLN_INCLUDE_ONLY + + template <typename E> + inline + Dindex_Site<E>::Dindex_Site() + { + typedef typename E::value_t value_t; + const value_t& (E::*m)() const = & E::value; + m = 0; + } + + + template <typename D> + inline + std::ostream& operator<<(std::ostream& ostr, const Dindex_Site<D>& dp) + { + ostr << '(' << debug::format(exact(dp).value()) << ')'; + return ostr; + } + + + template <typename L, typename R> + inline + bool operator==(const Dindex_Site<L>& lhs, const Dindex_Site<R>& rhs) + { + return exact(lhs).value() == exact(rhs).value(); + } + + template <typename L, typename R> + inline + L operator+(const Dindex_Site<L>& lhs, const Dindex_Site<R>& rhs) + { + L tmp(exact(lhs).value() + exact(rhs).value()); + return tmp; + } + + template <typename L, typename R> + inline + L operator-(const Dindex_Site<L>& lhs, const Dindex_Site<R>& rhs) + { + L tmp(exact(lhs).value() - exact(rhs).value()); + return tmp; + } + + template <typename L, typename S> + inline + L operator+(const Dindex_Site<L>& lhs, const value::Scalar<S>& rhs) + { + L tmp(exact(lhs).value() + exact(rhs).to_equiv()); + return tmp; + } + + template <typename L, typename S> + inline + L operator-(const Dindex_Site<L>& lhs, const value::Scalar<S>& rhs) + { + L tmp(exact(lhs).value() - exact(rhs).to_equiv()); + return tmp; + } + + template <typename D, typename S> + D operator*(const Dindex_Site<D>& lhs, const value::Scalar<S>& rhs) + { + D tmp(exact(lhs).value() * exact(rhs).to_equiv()); + return tmp; + } + + namespace convert + { + + namespace over_load + { + + template <typename D> + inline + void + from_to_(const Dindex_Site<D>& dp, mln_site(D)& p) + { + p.change_index(exact(dp).value()); + } + + } // end of namespace mln::convert::over_load + + } // end of namespace mln::convert + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_CORE_CONCEPT_DINDEX_SITE_HH Index: trunk/milena/sandbox/edwin/mln/core/concept/tree.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/concept/tree.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/concept/tree.hh (revision 4620) @@ -0,0 +1,148 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CORE_CONCEPT_TREE_HH +# define MLN_CORE_CONCEPT_TREE_HH + +# include <mln/core/concept/object.hh> + +namespace mln +{ + + // Forward declaration. + template <typename E> struct Tree; + + // Tree category flag type. + template <> + struct Tree<void> + { + typedef Object<void> super; + }; + + template <typename E> + struct Tree : public Object<E> + { + typedef Tree<void> category; + + /* + // Original image related + typedef site; + typedef psite; + + typedef value; + typedef rvalue; + typedef lvalue; + + // Node/Site related material. + typedef domain_t; + const domain_t& domain() const; + + typedef nodes_t; + const nodes_t& nodes() const; + + bool has(const node_t&) const; + bool has(const psite&) const; + + // Value related material. + rvalue f() (const psite&) const; + lvalue f() (const psite&); + rvalue f[] (const node_t&) const; + lvalue f[] (const node_t&); + + // Node relationship. + node_t node(const psite&) const; + void set_node(const psite&, const node_t&); + node_t parent(const node_id_t&) const; + void set_parent(const node_t&, const node_t&); + + // Node test materials + bool is_a_leaf(const node_t&) const; + bool is_a_root(const node_t&) const; + */ + + protected: + Tree(); + }; + +# ifndef MLN_INCLUDE_ONLY + + template <typename E> + inline + Tree<E>::Tree() + { + typedef mln_site(E) site; + typedef mln_psite(E) psite; + + typedef mln_value(E) value; + typedef mln_rvalue(E) rvalue; + typedef mln_lvalue(E) lvalue; + + typedef typename E::node_t node_t; + + // Site/Node related material. + typedef mln_domain(E) domain_t; + typedef typename E::nodes_t nodes_t; + + const domain_t& (E::*m1)() const = & E::domain; + m1 = 0; + const nodes_t& (E::*m2)() const = & E::nodes; + m2 = 0; + bool (E::*m3)(const node_t&) const = & E::has; + m3 = 0; + bool (E::*m4)(const psite&) const = & E::has; + m4 = 0; + + // Value related material. + rvalue (E::*m5)(const psite&) const = & E::f; + m5 = 0; + lvalue (E::*m6)(const psite&) = & E::f; + m6 = 0; + rvalue (E::*m7)(const node_t&) const = & E::f; + m7 = 0; + lvalue (E::*m8)(const node_t&) = & E::f; + m8 = 0; + + // Node relationship. + node_t (E::*m9)(const psite&) const = & E::node; + m9 = 0; + void (E::*m10)(const psite&, const node_t&) = & E::set_node; + m10 = 0; + node_t (E::*m11)(const node_t&) const = & E::parent; + m11 = 0; + void (E::*m12)(const node_t&, const node_t&) = & E::set_parent; + m12 = 0; + + // Node tests + bool (E::*m13)(const node_t&) const = & E::is_a_leaf; + m13 = 0; + bool (E::*m14)(const node_t&) const = & E::is_a_root; + m14 = 0; + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_CORE_CONCEPT_TREE_HH Index: trunk/milena/sandbox/edwin/mln/core/internal/index_site_base.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/internal/index_site_base.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/internal/index_site_base.hh (revision 4620) @@ -0,0 +1,254 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CORE_INTERNAL_INDEX_SITE_BASE_HH +# define MLN_CORE_INTERNAL_INDEX_SITE_BASE_HH + +# include <mln/core/concept/index_site.hh> +# include <mln/core/concept/proxy.hh> +# include <mln/value/concept/integer.hh> + +namespace mln +{ + /// \{ Forward declarations. + namespace literal + { + struct zero_t; + struct one_t; + } + + template <typename E> struct dindex_site; + /// \} + + + namespace internal + { + + template <typename E> struct index_site_base; + + template <typename E = void> + struct index_site_base : public Index_Site<E> + { + typedef index_site_base<E> self; + + typedef index_site_base<E> site; + typedef index_site_base<E> psite; + + typedef dindex_site<E> delta; + typedef dindex_site<E> dpsite; + + typedef unsigned index_t; + + /// Constructors + /// \{ + index_site_base(); + explicit index_site_base(unsigned i); + index_site_base(const literal::zero_t&); + index_site_base(const literal::one_t&); + /// \} + + /// Index materials + /// \{ + /// Return the current index. + const index_t& index() const; + /// Change the current index. + void change_index(const index_t&); + /// Increment the current index. + void inc_index(); + /// Decrement the current index. + void dec_index(); + /// \} + + /// Operators + /// \{ + self& operator+= (const delta&); + self& operator-= (const delta&); + /// \} + + protected: + index_t i_; + }; + + + /// subject_impl specialization (Proxy) + /// \{ + + template <typename P, typename E> + struct subject_impl< const index_site_base<P>, E > + { + //const typename index_site_base<P>::index_t& index() const; + + private: + const E& exact_() const; + }; + + template <typename P, typename E> + struct subject_impl< index_site_base<P>, E > : + subject_impl< const index_site_base<P>, E > + { + //void change_index(const typename index_site_base<P>::index_t& idx); + void inc_index(); + void dec_index(); + + private: + E& exact_(); + }; + + /// \} + + +# ifndef MLN_INCLUDE_ONLY + + template <typename E> + inline + index_site_base<E>::index_site_base() + { + } + + template <typename E> + inline + index_site_base<E>::index_site_base(unsigned i) + : i_ (i) + { + } + + template <typename E> + inline + index_site_base<E>::index_site_base(const literal::zero_t&) + : i_ (0) + { + } + + template <typename E> + inline + index_site_base<E>::index_site_base(const literal::one_t&) + : i_ (1) + { + } + + template <typename E> + inline + const typename index_site_base<E>::index_t& + index_site_base<E>::index() const + { + return i_; + } + + template <typename E> + inline + void + index_site_base<E>::dec_index() + { + --i_; + } + + template <typename E> + inline + void + index_site_base<E>::inc_index() + { + ++i_; + } + + + template <typename E> + inline + void + index_site_base<E>::change_index(const index_t& idx) + { + i_ = idx; + } + + template <typename E> + inline + index_site_base<E>& + index_site_base<E>::operator+=(const delta& dp) + { + i_ += dp.value(); + return *this; + } + + template <typename E> + inline + index_site_base<E>& + index_site_base<E>::operator-=(const delta& dp) + { + mln_precondition(dp.value() >= i_); + i_ -= dp.value(); + return *this; + } + + + template <typename P, typename E> + const E& + subject_impl< const index_site_base<P>, E >::exact_() const + { + return internal::force_exact<const E>(*this); + } + + template <typename P, typename E> + E& + subject_impl< index_site_base<P>, E >::exact_() + { + return internal::force_exact<E>(*this); + } + + // template <typename P, typename E> + // const typename index_site_base<P>::index_t& + // subject_impl< const index_site_base<P>, E >::index() const + // { + // return exact_().get_subject().index(); + // } + + // template <typename P, typename E> + // void + // subject_impl< index_site_base<P>, E >::change_index(const typename index_site_base<P>::index_t& idx) + // { + // return exact_().get_subject().change_index(idx); + // } + + template <typename P, typename E> + void + subject_impl< index_site_base<P>, E >::inc_index() + { + return exact_().get_subject().inc_index(); + } + + template <typename P, typename E> + void + subject_impl< index_site_base<P>, E >::dec_index() + { + return exact_().get_subject().dec_index(); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::internal + +} // end of namespace mln + +# include <mln/core/dindex_site.hh> + +#endif // !MLN_CORE_INDEX_SITE_BASE_HH Index: trunk/milena/sandbox/edwin/mln/core/dindex_site.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/core/dindex_site.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/core/dindex_site.hh (revision 4620) @@ -0,0 +1,119 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_CORE_DINDEX_SITE_HH +# define MLN_CORE_DINDEX_SITE_HH + +# include <mln/core/concept/index_site.hh> +# include <mln/core/concept/dindex_site.hh> + +namespace mln +{ + /// \{ Forward declarations. + namespace literal { + struct zero_t; + struct one_t; + } + /// \} + + + template <typename P> struct dindex_site; + + template <typename P> + struct dindex_site : public Dindex_Site< dindex_site<P> > + { + typedef P site; + typedef P psite; + + typedef int value_t; + + /// Constructors + /// \{ + dindex_site(); + dindex_site(int i); + dindex_site(const literal::zero_t&); + dindex_site(const literal::one_t&); + /// \} + + /// Value access + /// \{ + const value_t& value() const; + void change_value(const value_t& v); + /// \} + + protected: + value_t v_; + }; + +# ifndef MLN_INCLUDE_ONLY + + template <typename P> + inline + dindex_site<P>::dindex_site() + { + } + + template <typename P> + inline + dindex_site<P>::dindex_site(int i) + : v_ (i) + { + } + + template <typename P> + inline + dindex_site<P>::dindex_site(const literal::zero_t&) + : v_ (0) + { + } + + template <typename P> + inline + dindex_site<P>::dindex_site(const literal::one_t&) + : v_ (1) + { + } + + template <typename P> + inline + const typename dindex_site<P>::value_t& + dindex_site<P>::value() const + { + return v_; + } + + template <typename P> + inline + void + dindex_site<P>::change_value(const value_t& v) + { + v_ = v; + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_CORE_DINDEX_SITE_HH Index: trunk/milena/sandbox/edwin/mln/util/ctree/ctree.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/util/ctree/ctree.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/util/ctree/ctree.hh (revision 4620) @@ -0,0 +1,589 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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. + +/// FIXME: because there're some stuffs not enough clear... +/// In the previous implementation of the morpho tree, the site set and +/// the domain set had the same type, so that +/// E(nodes) is included in E(sites). In fact, (I think) that's a +/// mistake that comes from the representation using parent image. For +/// real, the tree can be considered as a triplet (node_set, function, +/// relationship) (N, F, R) such that F: node -> (site_set, value) and +/// R: parent node -> node and N: the node set. +/// +/// Currently, the node type is not a site but it should +/// be. And so, the set of nodes: nodes_t < Site_Set. +/// We should implement (but I don't know how to make it well) the type +/// Attribute_image < Image that have two kind of sites +/// (node and site of the original image) with +/// overloaded operator(): node -> value +/// mln_psite(nodes_t) -> value +/// +/// + +/// The differences and what they imply. +/// Attribute_image a; Tree t +/// Node_Set nodes; Site_Set s; +/// +/// I'd like to be able to write: +/// a | (subset of t.nodes) as whell as a | (subset of t.domain()) + +// \todo definition of site, psite is ambigous, replace with content_t +// or other. +// \todo node operator ? + + + +#ifndef MLN_UTIL_CTREE_CTREE_HH +# define MLN_UTIL_CTREE_CTREE_HH + +# include <mln/core/concept/image.hh> +# include <mln/core/concept/site_set.hh> +# include <mln/util/ctree/internal/tree_base.hh> +# include <algorithm> + +namespace mln +{ + + /// Forward declaration. + namespace util { namespace ctree { template <typename I> class ctree; } } + + namespace internal + { + /// Data structure for component tree. + template <> + template <typename I> + struct data< util::ctree::ctree<I> > + { + typedef util::ctree::ctree<I> T; + typedef typename T::node_t::index_t index_t; + + data(const I&); + ~data(); + + mln_ch_value(I, index_t) map_; + std::vector<index_t> parent_; + std::vector<unsigned> n_nodes_; + std::vector<mln_value(I)> values_; + + const mln_domain(I)& domain_; + typename T::nodes_t nodes_; + }; + + } // end of namespace mln::internal + + namespace util + { + + namespace ctree + { + + template <typename I> + struct ctree : public internal::tree_base< I, ctree<I> > + { + /// The super class. + typedef internal::tree_base<I, ctree<I> > super; + + /// Site related type definitions. + /// \{ + /// The type of site. + typedef mln_site(I) site; + /// The type of pseudo-site. + typedef mln_psite(I) psite; + /// The type of domain. + typedef mln_domain(I) domain_t; + /// \} + + /// Node related type definions. + /// \{ + /// The type of node. + typedef typename super::node_t node_t; + /// The type of node set. + typedef typename super::nodes_t nodes_t; + /// \} + + /// Node/Site value related type definitions. + /// \{ + /// The type of node value + typedef mln_value(I) value; + /// The type of node rvalue. + typedef mln_rvalue(I) rvalue; + /// The type of node lvalue. + typedef mln_lvalue(I) lvalue; + /// \} + + /// Constructors + /// \{ + ctree(); + + /// Constructor from union-find results. + /// \param[in] f The input image. + /// \param[in] parent The (not necessary canonized) parent image. + /// \param[in] area The number of nodes in each sub-tree. + /// \param[in] s The sorted site set. + /// \param[in] nb_nodes The total number of nodes. + template <typename S> + ctree(const Image<I>& f, + const Site_Set<S>& s, + mln_ch_value(I, psite)& parent, + mln_ch_value(I, unsigned)& area, + unsigned nb_nodes); + /// \} + + /// Misc. + /// \{ + const domain_t& domain() const; + const nodes_t& nodes() const; + bool has(const psite&) const; + bool has(const node_t&) const; + unsigned n_nodes() const; + /// \} + + /// Value access material. + /// \{ + rvalue f(const psite&) const; + lvalue f(const psite&); + rvalue f(const node_t&) const; + lvalue f(const node_t&); + /// \} + + /// Node relationship material. + /// \{ + node_t node(const psite&) const; + void set_node(const psite&, const node_t&); + node_t parent(const node_t&) const; + void set_parent(const node_t& n, const node_t& parent); + + /// Return the node set of the sub-tree of \p n. + nodes_t desc(const node_t& n) const; + /// Return the node set of ancestors of \p n. + nodes_t anc(const node_t& n) const; + /// \} + + /// Node tests material. + /// \{ + bool is_a_leaf(const node_t&) const; + bool is_a_root(const node_t&) const; + /// \} + + /// Fast access material. + /// \{ + bool has_index(unsigned i) const; + rvalue f_at_(unsigned i) const; + lvalue f_at_(unsigned i); + unsigned parent_at_(unsigned i) const; + unsigned& parent_at_(unsigned i); + unsigned node_at_(const psite& p) const; + unsigned& node_at_(const psite& p); + /// \} + + /// To attribute image + attribute_image<ctree<I>, value> to_image() const; + + /// Site -> node function. + /// \{ + /// Return the map Site -> Node as a V2V function. + //pw::value< mln_ch_value(I, node_t) > mapper() const; + /// \} + + }; + + } // end of namespace mln::util::ctree + + } // end of namespace mln::util + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + template <typename I> + inline + data< util::ctree::ctree<I> >::data(const I& f) + : domain_ (f.domain()) + { + } + + template <typename I> + inline + data< util::ctree::ctree<I> >::~data() + { + } + + } // end of namespace mln::internal + + namespace util + { + + namespace ctree + { + namespace internal + { + template <typename T> + struct create_node : Function_v2v< create_node<T> > + { + typedef typename T::index_t param; + typedef typename T::node_t result; + + create_node(const T& tree) + : tree_ (tree) + { + } + + result + operator()(const param& idx) const + { + result tmp(tree_, idx); + return tmp; + } + + private: + const T& tree_; + }; + } + + + template <typename I> + inline + ctree<I>::ctree() + { + } + + template <typename I> + template <typename S> + inline + ctree<I>::ctree(const Image<I>& f_, + const Site_Set<S>& s_, + mln_ch_value(I, mln_psite(I))& parent, + mln_ch_value(I, unsigned)& area, + unsigned nb_nodes) + { + const I& f = exact(f_); + const S& s = exact(s_); + + mln_precondition(f.is_valid()); + mln_precondition(s.is_valid()); + mln_precondition(parent.is_valid()); + mln_precondition(area.is_valid()); + mln_precondition(f.domain() == parent.domain()); + mln_precondition(f.domain() == area.domain()); + mln_precondition(f.domain().nsites() == s.nsites()); + + this->data_ = new mln::internal::data< ctree<I> >(f); + + initialize(this->data_->map_, f); + this->data_->parent_.resize(nb_nodes); + this->data_->n_nodes_.resize(nb_nodes); + this->data_->values_.resize(nb_nodes); + this->data_->nodes_.init(node_t(*this, 0), nb_nodes); + + //debug::println("Parent: ", parent); + //debug::println("Area: ", area); + + unsigned root_offset = 0; + mln_fwd_piter(S) p(s); + for_all(p) + { + psite q = parent(p); + + if (f(parent(q)) == f(q)) // Canonization + q = (parent(p) = parent(q)); + + if (f(p) == f(q) && p != q) // Not a node. + { + this->data_->map_(p) = this->data_->map_(parent(p)); + } + else + { + unsigned& offset = (p == q) ? root_offset : area(q); + + // Insert Node. + mln_assertion(offset < nb_nodes); + this->data_->map_(p) = offset; + this->data_->parent_[offset] = this->data_->map_(q); + this->data_->values_[offset] = f(p); + this->data_->n_nodes_[offset] = area(p); + area(p) = offset + 1; + offset += this->data_->n_nodes_[offset] + 1; + } + } + } + + + template <typename I> + inline + const mln_domain(I)& + ctree<I>::domain() const + { + return this->data_->domain_; + } + + template <typename I> + inline + const typename ctree<I>::nodes_t& + ctree<I>::nodes() const + { + return this->data_->nodes_; + } + + template <typename I> + inline + unsigned + ctree<I>::n_nodes() const + { + mln_precondition(this->is_valid()); + return this->data_->nodes_.nsites(); + } + + template <typename I> + inline + bool + ctree<I>::has(const mln_psite(I)& p) const + { + mln_precondition(this->is_valid()); + return this->data_->domain_.has(p); + } + + template <typename I> + inline + bool + ctree<I>::has(const node_t& n) const + { + mln_precondition(this->is_valid()); + return n.index() < this->data_->nodes_.nsites(); + } + + template <typename I> + inline + mln_rvalue(I) + ctree<I>::f (const mln_psite(I)& p) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(p)); + return this->data_->values_[this->data_->map_(p)]; + } + + template <typename I> + inline + mln_lvalue(I) + ctree<I>::f (const mln_psite(I)& p) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(p)); + return this->data_->values_[this->data_->map_(p)]; + } + + template <typename I> + inline + mln_rvalue(I) + ctree<I>::f (const node_t& n) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + return this->data_->values_[n.index()]; + } + + template <typename I> + inline + mln_lvalue(I) + ctree<I>::f (const node_t& n) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + return this->data_->values_[n.index()]; + } + + template <typename I> + inline + typename ctree<I>::node_t + ctree<I>::node(const mln_psite(I)& p) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(p)); + node_t tmp(*this, this->data_->map_(p)); + mln_postcondition(this->has(tmp)); + return tmp; + } + + template <typename I> + inline + void + ctree<I>::set_node(const mln_psite(I)& p, const node_t& n) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(p)); + mln_precondition(this->has(n)); + this->data_->map_(p) = n.index(); + } + + + template <typename I> + inline + typename ctree<I>::node_t + ctree<I>::parent(const node_t& n) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + node_t tmp(*this, this->data_->parent_[n.index()]); + mln_postcondition(tmp.index() < n.index()); + return tmp; + } + + template <typename I> + inline + void + ctree<I>::set_parent(const node_t& n, const node_t& parent) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + mln_precondition(this->has(parent)); + this->data_->parent_[n.index()] = parent.index(); + } + + template <typename I> + inline + typename ctree<I>::nodes_t + ctree<I>::desc(const node_t& n) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + nodes_t tmp(n, this->data_->n_nodes_[n.index()] + 1); + return tmp; + } + + template <typename I> + inline + bool + ctree<I>::is_a_root(const node_t& n) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + return (this->data_->parent_[n.index()] == n.index()); + } + + template <typename I> + inline + bool + ctree<I>::is_a_leaf(const node_t& n) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(n)); + return (this->data_->n_nodes_[n.index()] == 0); + } + + template <typename I> + inline + bool + ctree<I>::has_index(unsigned i) const + { + mln_precondition(this->is_valid()); + return i <= this->n_nodes(); + } + + template <typename I> + inline + mln_rvalue(I) + ctree<I>::f_at_(unsigned i) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has_index(i)); + return this->data_->values_[i]; + } + + template <typename I> + inline + mln_lvalue(I) + ctree<I>::f_at_(unsigned i) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has_index(i)); + return this->data_->values_[i]; + } + + template <typename I> + inline + unsigned + ctree<I>::parent_at_(unsigned i) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has_index(i)); + mln_postcondition(this->has_index(this->data_->parent_[i])); + return this->data_->parent_[i]; + } + + template <typename I> + inline + unsigned& + ctree<I>::parent_at_(unsigned i) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has_index(i)); + mln_postcondition(this->has_index(this->data_->parent_[i])); + return this->data_->parent_[i]; + } + + template <typename I> + inline + unsigned + ctree<I>::node_at_(const psite& p) const + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(p)); + mln_postcondition(this->has_index(this->data_->map_(p))); + return this->data_->map_(p); + } + + template <typename I> + inline + unsigned& + ctree<I>::node_at_(const psite& p) + { + mln_precondition(this->is_valid()); + mln_precondition(this->has(p)); + mln_postcondition(this->has_index(this->data_->map_(p))); + return this->data_->map_(p); + } + + template <typename I> + inline + attribute_image<ctree<I>, mln_value(I)> + ctree<I>::to_image() const + { + mln_precondition(this->is_valid()); + + attribute_image<ctree<I>, value> to(*this); + std::copy(this->data_->values_.begin(), this->data_->values_.end(), to.buffer()); + return to; + } + + + } // end of namespace mln::util::ctree + + } // end of namespace mln::util + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_UTIL_CTREE_CTREE_HH Index: trunk/milena/sandbox/edwin/mln/util/ctree/node.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/util/ctree/node.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/util/ctree/node.hh (revision 4620) @@ -0,0 +1,183 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_UTIL_CTREE_NODE_HH +# define MLN_UTIL_CTREE_NODE_HH + +# include <mln/core/internal/index_site_base.hh> + +namespace mln +{ + + /// Node category flag type. + template <typename E> struct Node {}; + + template <> + struct Node<void> + { + typedef Index_Site<void> super; + }; + + namespace util + { + + namespace ctree + { + + template <typename T> + class node : public internal::index_site_base< node<T> > + { + public: + /// Object category. + typedef Node<void> category; + + typedef internal::index_site_base<node> super; + + typedef typename super::index_t index_t; + + /// Constructors + /// \{ + node(); + node(const Tree<T>& tree); + node(const Tree<T>& tree, const index_t& id); + /// \} + + /// Return whether the node is valid. + const T& tree() const; + void change_target(const Tree<T>& tree); + + private: + const T* tree_; + }; + + } // end of namespace mln::util::ctree + + } // end of namespace mln::util + + namespace internal + { + + /// subject_impl specialization (Proxy) + /// \{ + + template <typename T, typename E> + struct subject_impl< const util::ctree::node<T>, E > : + subject_impl< const internal::index_site_base< util::ctree::node<T> > , E > + { + const T& tree() const; + + private: + const E& exact_() const; + }; + + template <typename T, typename E> + struct subject_impl< util::ctree::node<T>, E > : + subject_impl< const util::ctree::node<T>, E >, + subject_impl< internal::index_site_base< util::ctree::node<T> > , E > + { + }; + + /// \} + + } // end of namespace mln::internal + +# ifndef MLN_INCLUDE_ONLY + + namespace util + { + + namespace ctree + { + + template <typename T> + inline + node<T>::node() + : tree_ (0) + { + } + + template <typename T> + inline + node<T>::node(const Tree<T>& tree) + : tree_ (&(exact(tree))) + { + } + + + template <typename T> + inline + node<T>::node(const Tree<T>& tree, const index_t& i) + : super(i), + tree_ (&(exact(tree))) + { + } + + template <typename T> + inline + const T& + node<T>::tree() const + { + return tree_; + } + + template <typename T> + inline + void + node<T>::change_target(const Tree<T>& tree) + { + tree_ = &(exact(tree)); + } + + + } // end of namespace mln::util::ctree + + } // end of namespace mln::util + + namespace internal + { + + template <typename T, typename E> + inline + const E& + subject_impl< const util::ctree::node<T>, E >::exact_() const + { + return internal::force_exact<const E>(*this); + } + + template <typename T, typename E> + inline + const T& + subject_impl< const util::ctree::node<T>, E >::tree() const + { + return exact_().get_subject().tree(); + } + + } // end of namespace mln::internal + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +#endif // !MLN_UTIL_CTREE_NODE_HH Index: trunk/milena/sandbox/edwin/mln/util/ctree/internal/tree_base.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/util/ctree/internal/tree_base.hh (revision 0) +++ trunk/milena/sandbox/edwin/mln/util/ctree/internal/tree_base.hh (revision 4620) @@ -0,0 +1,140 @@ +// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// +// This file is part of Olena. +// +// Olena is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation, version 2 of the License. +// +// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>. +// +// As a special exception, you may use this file as part of a free +// software project 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_UTIL_CTREE_INTERNAL_TREE_BASE_HH +# define MLN_UTIL_CTREE_INTERNAL_TREE_BASE_HH + +# include <mln/core/concept/object.hh> +# include <mln/core/concept/tree.hh> +# include <mln/core/concept/proxy.hh> +# include <mln/core/internal/data.hh> + +# include <mln/core/site_set/p_run_idx.hh> + +# include <mln/util/ctree/node.hh> +# include <mln/util/tracked_ptr.hh> + +namespace mln +{ + + namespace util + { + + namespace ctree + { + + namespace internal + { + + template <typename I, typename E> + class tree_base : public Tree<E> + { + public: + /// Site related type definitions. + /// \{ + /// The type of site. + typedef mln_site(I) site; + /// The type of pseudo-site. + typedef mln_psite(I) psite; + /// The type of domain. + typedef mln_domain(I) domain_t; + /// \} + + /// Node related type definions. + /// \{ + /// The type of the node. + typedef ctree::node<E> node_t; + /// The type of node set. + typedef p_run_idx<node_t> nodes_t; + /// \} + + /// Node/Site value related type definitions. + /// \{ + /// The type of node value + typedef mln_value(I) value; + /// The type of node rvalue. + typedef mln_rvalue(I) rvalue; + /// The type of node lvalue. + typedef mln_lvalue(I) lvalue; + /// \} + + /// Check validity. + bool is_valid() const; + void invalidate(); + + /// Hook to data; for debugging purpose. + const util::tracked_ptr< mln::internal::data<E> >& data_hook_() const; + + public: // Tmp for construction. + util::tracked_ptr< mln::internal::data<E> > data_; + protected: + tree_base(); + }; + +# ifndef MLN_INCLUDE_ONLY + + template<typename I, typename E> + inline + tree_base<I,E>::tree_base() + : data_ (0) + { + } + + template <typename I, typename E> + inline + bool + tree_base<I,E>::is_valid() const + { + return data_ != 0; + } + + template <typename I, typename E> + inline + void + tree_base<I,E>::invalidate() + { + data_.clean_(); + } + + template<typename I, typename E> + inline + const util::tracked_ptr< mln::internal::data<E> >& + tree_base<I,E>::data_hook_() const + { + return data_; + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::util::ctree::internal + + } // end of namespace mln::util::ctree + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif // !MLN_UTIL_CTREE_INTERNAL_TREE_BASE_HH
participants (1)
-
Edwin Carlinet