* mln/accu/all.hh: include new accumulators.
* mln/accu/count_labels.hh: count how many different labels are in an
image.
* mln/accu/label_used.hh: Reference all the different labels used.
---
milena/ChangeLog | 11 +++
milena/mln/accu/all.hh | 2 +
milena/mln/accu/count_labels.hh | 175 +++++++++++++++++++++++++++++++++++++++
milena/mln/accu/label_used.hh | 159 +++++++++++++++++++++++++++++++++++
4 files changed, 347 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/accu/count_labels.hh
create mode 100644 milena/mln/accu/label_used.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f07f826..c7c171e 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,14 @@
+2009-04-07 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
+ Add new accumulators related to labels.
+
+ * mln/accu/all.hh: include new accumulators.
+
+ * mln/accu/count_labels.hh: count how many different labels are in an
+ image.
+
+ * mln/accu/label_used.hh: Reference all the different labels used.
+
2009-04-06 Frederic Bour <bour(a)lrde.epita.fr>
Clean new fun implementation.
diff --git a/milena/mln/accu/all.hh b/milena/mln/accu/all.hh
index 0e4d72d..5dfe51e 100644
--- a/milena/mln/accu/all.hh
+++ b/milena/mln/accu/all.hh
@@ -58,10 +58,12 @@ namespace mln
# include <mln/accu/bbox.hh>
# include <mln/accu/count.hh>
+# include <mln/accu/count_labels.hh>
# include <mln/accu/center.hh>
//# include <mln/accu/count_adjacent_vertices.hh>
# include <mln/accu/height.hh>
# include <mln/accu/histo.hh>
+# include <mln/accu/label_used.hh>
# include <mln/accu/land.hh>
# include <mln/accu/land_basic.hh>
# include <mln/accu/line.hh>
diff --git a/milena/mln/accu/count_labels.hh b/milena/mln/accu/count_labels.hh
new file mode 100644
index 0000000..533e736
--- /dev/null
+++ b/milena/mln/accu/count_labels.hh
@@ -0,0 +1,175 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_ACCU_COUNT_LABELS_HH
+# define MLN_ACCU_COUNT_LABELS_HH
+
+/// \file mln/accu/count_labels.hh
+///
+/// Define an accumulator that counts the number of different labels.
+
+# include <mln/accu/internal/base.hh>
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/metal/is_a.hh>
+
+namespace mln
+{
+
+ // Forward declaration.
+ namespace value { template <typename E> struct Symbolic; }
+
+ namespace accu
+ {
+
+ /// Generic counter accumulator class.
+ /// The parameter \a L is the label type to be count.
+ template <typename L>
+ struct count_labels
+ : public mln::accu::internal::base< unsigned , count_labels<L> >,
+ mlc_is_a(L, mln::value::Symbolic)::check_t
+ {
+ typedef L argument;
+
+ count_labels();
+
+ /// Manipulators.
+ /// \{
+ void init();
+ void take(const argument&);
+ void take(const count_labels<L>& other);
+
+ /// Force the value of the counter to \a c.
+ void set_value(unsigned c);
+ /// \}
+
+ /// Get the value of the accumulator.
+ unsigned to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
+ bool is_valid() const;
+
+ protected:
+ /// The value of the counter.
+ unsigned count_labels_;
+ std::vector<bool> deja_vu_;
+ };
+
+
+ namespace meta
+ {
+
+ /// Meta accumulator for count_labels.
+ struct count_labels : public Meta_Accumulator< count_labels >
+ {
+ template <typename L>
+ struct with
+ {
+ typedef accu::count_labels<L> ret;
+ };
+ };
+
+ } // end of namespace mln::accu::meta
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename L>
+ inline
+ count_labels<L>::count_labels()
+ {
+ init();
+ }
+
+ template <typename L>
+ inline
+ void
+ count_labels<L>::init()
+ {
+ count_labels_ = 0;
+ deja_vu_.resize(mln_max(L), false);
+ }
+
+ template <typename L>
+ inline
+ void
+ count_labels<L>::take(const argument& l)
+ {
+ if (!deja_vu_[l])
+ {
+ ++count_labels_;
+ deja_vu_[l] = true;
+ }
+ //else
+ // No-op
+ }
+
+ template <typename L>
+ inline
+ void
+ count_labels<L>::take(const count_labels<L>& other)
+ {
+ count_labels_ += other.count_labels_;
+ for (unsigned i = 0; i < deja_vu_.size(); ++i)
+ deja_vu_[i] = deja_vu_[i] || other.deja_vu_[i];
+ }
+
+ template <typename L>
+ inline
+ unsigned
+ count_labels<L>::to_result() const
+ {
+ // The background label MUST not be counted.
+ return count_labels_ - 1;
+ }
+
+ template <typename L>
+ inline
+ void
+ count_labels<L>::set_value(unsigned c)
+ {
+ count_labels_ = c;
+ }
+
+ template <typename L>
+ inline
+ bool
+ count_labels<L>::is_valid() const
+ {
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_COUNT_LABELS_HH
diff --git a/milena/mln/accu/label_used.hh b/milena/mln/accu/label_used.hh
new file mode 100644
index 0000000..6323d3e
--- /dev/null
+++ b/milena/mln/accu/label_used.hh
@@ -0,0 +1,159 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_ACCU_LABEL_USED_HH
+# define MLN_ACCU_LABEL_USED_HH
+
+/// \file mln/accu/label_used.hh
+///
+/// Define an accumulator that references all the labels used.
+
+# include <mln/accu/internal/base.hh>
+# include <mln/core/concept/meta_accumulator.hh>
+# include <mln/math/max.hh>
+
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+ /// Define an accumulator that references all the labels used.
+ /// The parameter \a L is the label type.
+ template <typename L>
+ struct label_used : public mln::accu::internal::base< const fun::i2v::array<bool>& , label_used<L> >
+ {
+ typedef L argument;
+
+ label_used();
+
+ /// Initialize accumulator attributes.
+ void init();
+
+ /// Manipulators.
+ /// \{
+ void take(const argument&);
+ void take(const label_used<L>& other);
+ /// \}
+
+ /// Get the value of the accumulator.
+ const fun::i2v::array<bool>& to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
+ bool is_valid() const;
+
+ protected:
+ /// True if a label is used.
+ fun::i2v::array<bool> label_used_;
+ };
+
+
+ namespace meta
+ {
+
+ /// Meta accumulator for label_used.
+ struct label_used : public Meta_Accumulator< label_used >
+ {
+ template <typename L>
+ struct with
+ {
+ typedef accu::label_used<L> ret;
+ };
+ };
+
+ } // end of namespace mln::accu::meta
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename L>
+ inline
+ label_used<L>::label_used()
+ {
+ init();
+ }
+
+ template <typename L>
+ inline
+ void
+ label_used<L>::init()
+ {
+ label_used_.resize(1, true);
+ }
+
+ template <typename L>
+ inline
+ void
+ label_used<L>::take(const argument& l)
+ {
+ if (label_used_.size() <= l)
+ label_used_.resize(l.next(), false);
+
+ label_used_(l) = true;
+ }
+
+ template <typename L>
+ inline
+ void
+ label_used<L>::take(const label_used<L>& other)
+ {
+ unsigned
+ max_size = math::max(other.to_result().size(), label_used_.size());
+
+ label_used_.resize(max_size, false);
+ for (unsigned i = 1; i < label_used_.size(); ++i)
+ label_used_(i) = label_used_(i) || other.to_result()(i);
+ }
+
+ template <typename L>
+ inline
+ const fun::i2v::array<bool>&
+ label_used<L>::to_result() const
+ {
+ return label_used_;
+ }
+
+ template <typename L>
+ inline
+ bool
+ label_used<L>::is_valid() const
+ {
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_LABEL_USED_HH
--
1.5.6.5
---
milena/ChangeLog | 4 +
milena/mln/util/fibonacci_heap.hh | 2126 ++++++++++++++++++------------------
2 files changed, 1067 insertions(+), 1063 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 306a838..f8bdc57 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,9 @@
2009-04-06 Roland Levillain <roland(a)lrde.epita.fr>
+ * mln/util/fibonacci_heap.hh: Convert to Unix line terminators.
+
+2009-04-06 Roland Levillain <roland(a)lrde.epita.fr>
+
* mln/util/ord_pair.hh: Remove outdated FIXME.
2009-04-06 Roland Levillain <roland(a)lrde.epita.fr>
diff --git a/milena/mln/util/fibonacci_heap.hh b/milena/mln/util/fibonacci_heap.hh
index ef85508..597d87a 100644
--- a/milena/mln/util/fibonacci_heap.hh
+++ b/milena/mln/util/fibonacci_heap.hh
@@ -1,1063 +1,1063 @@
-// Copyright (C) 2009 EPITA Research and Development Laboratory
-// (LRDE)
-//
-// This file is part of the Olena Library. This library is free
-// software; you can redistribute it and/or modify it under the terms
-// of the GNU General Public License version 2 as published by the
-// Free Software Foundation.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this library; see the file COPYING. If not, write to
-// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-// Boston, MA 02111-1307, USA.
-//
-// As a special exception, you may use this file as part of a free
-// software library without restriction. Specifically, if other files
-// instantiate templates or use macros or inline functions from this
-// file, or you compile this file and link it with other files to
-// produce an executable, this file does not by itself cause the
-// resulting executable to be covered by the GNU General Public
-// License. This exception does not however invalidate any other
-// reasons why the executable file might be covered by the GNU General
-// Public License.
-//
-//***************************************************************************
-// The Fibonacci heap implementation is Copyright (c) 1996 by John Boyer
-//
-// Once this Fibonacci heap implementation (the software) has been published
-// by Dr. Dobb's Journal, permission to use and distribute the software is
-// granted provided that this copyright notice remains in the source and
-// and the author (John Boyer) is acknowledged in works that use this program.
-//
-// Every effort has been made to ensure that this implementation is free of
-// errors. Nonetheless, the author (John Boyer) assumes no liability regarding
-// your use of this software.
-//
-// The author would also be very glad to hear from anyone who uses the
-// software or has any feedback about it.
-// Email: jboyer(a)gulf.csc.uvic.ca
-//***************************************************************************
-
-
-#ifndef MLN_UTIL_FIBONACCI_HEAP_HH
-# define MLN_UTIL_FIBONACCI_HEAP_HH
-
-
-# include <iostream>
-# include <mln/core/concept/object.hh>
-# include <mln/util/ord.hh>
-
-
-
-namespace mln
-{
-
- namespace util
- {
-
-
- namespace internal
- {
-
- /*--------------------------\
- | Fibonacci Heap node Class |
- `--------------------------*/
-
- template <typename P, typename T>
- class fibonacci_heap_node
- {
-
- public:
- /// Default constructor.
- fibonacci_heap_node();
-
- /// Construct a new node with \p value as value.
- fibonacci_heap_node(const P& priority, const T& value);
-
- ~fibonacci_heap_node();
-
- /// Return the node value.
- const T& value() const;
-
- const P& priority() const;
-
- fibonacci_heap_node<P,T> *left() const;
- fibonacci_heap_node<P,T> *right() const;
- fibonacci_heap_node<P,T> *parent() const;
- fibonacci_heap_node<P,T> *child() const;
-
- short degree() const;
-
- short mark() const;
-
-
- void set_value(const T&);
- void set_left(fibonacci_heap_node<P,T> *node);
- void set_right(fibonacci_heap_node<P,T> *node);
- void set_parent(fibonacci_heap_node<P,T> *node);
- void set_child(fibonacci_heap_node<P,T> *node);
- void set_degree(short degree);
- void set_mark(short mark);
-
- void operator=(fibonacci_heap_node<P,T>& rhs);
- bool operator==(fibonacci_heap_node<P,T>& rhs);
- bool operator<(fibonacci_heap_node<P,T>& rhs);
-
- void print_() const;
-
-
- private:
-
- fibonacci_heap_node<P,T> *left_;
- fibonacci_heap_node<P,T> *right_;
- fibonacci_heap_node<P,T> *parent_;
- fibonacci_heap_node<P,T> *child_;
- short degree_;
- short mark_;
- P priority_;
- T value_;
- };
-
- } // end of namespace mln::util::internal
-
-
-
- /*---------------------\
- | Fibonacci Heap Class |
- `---------------------*/
-
- template <typename P, typename T>
- class fibonacci_heap : public Object< fibonacci_heap<P,T> >
- {
- public:
-
- typedef T element;
-
- /// Default constructor
- fibonacci_heap();
-
- /// Copy constructor
- /// Be ware that once this heap is constructed, the argument \p node
- /// is cleared and all its elements are part of this new heap.
- fibonacci_heap(const fibonacci_heap<P,T>& node);
-
- ~fibonacci_heap();
-
- /// Push a new element in the heap.
- /// \sa insert
- void push(const P& priority, const T& value);
-
- /// Take \p other_heap's elements and insert them in this heap.
- /// After this call \p other_heap is cleared.
- void push(fibonacci_heap<P,T>& other_heap);
-
- /// Return the minimum value in the heap.
- const T& front() const;
-
- /// Return and remove the minimum value in the heap.
- T pop_front();
-
- /// Is it empty?
- bool is_empty() const;
-
- /// return false if it is empty.
- bool is_valid() const;
-
- /// Return the number of elements.
- unsigned nelements() const;
-
- /// Clear all elements in the heap and make the heap empty.
- void clear();
-
- /// Assignment operator.
- /// Be ware that this operator do *not* copy the data from \p rhs to this heap.
- /// It moves all elements which means that afterwards, \p rhs is
- /// is cleared and all its elements are part of this new heap.
- fibonacci_heap<P,T>& operator=(fibonacci_heap<P,T>& rhs);
-
-
-
- std::ostream& print_(std::ostream& cout,
- internal::fibonacci_heap_node<P,T> *tree = 0,
- internal::fibonacci_heap_node<P,T> *parent = 0) const;
-
- private:
-
- // Internal functions that help to implement the Standard Operations
-
-
- /// Allow to change a node value.
- /// FIXME: cannot use that function efficiently except by passing the
- /// node pointer. Any idea?
- /// FIXME: may be part of the public interface.
- int decrease_key(internal::fibonacci_heap_node<P,T> *node,
- internal::fibonacci_heap_node<P,T>& key);
-
- /// Remove node \p node from the child list of its parent node.
- /// FIXME: cannot use that function efficiently except by passing the
- /// node pointer. Any idea?
- /// FIXME: may be part of the public interface.
- int remove(internal::fibonacci_heap_node<P,T> *node);
-
- /// Insert a new node \p node in the heap.
- void insert(internal::fibonacci_heap_node<P,T> *node);
-
- /// Swap the two given nodes.
- void exchange(internal::fibonacci_heap_node<P,T>*& lhs,
- internal::fibonacci_heap_node<P,T>*& rhs);
-
- /// Internal function that reorganizes heap as part of an pop_front().
- /// We must find new minimum in heap, which could be anywhere along the
- /// root list. The search could be O(n) since all nodes could be on
- /// the root list. So, we reorganize the tree into more of a binomial
- /// forest structure, and then find the new minimum on the consolidated
- /// O(lg n) sized root list, and in the process set each Parent pointer
- /// to 0, and count the number of resulting subtrees.
- ///
- /// Note that after a list of n inserts, there will be n nodes on the
- /// root list, so the first pop_front() will be O(n) regardless of
- /// whether or not we consolidate. However, the consolidation causes
- /// subsequent pop_front() operations to be O(lg n). Furthermore,
- /// the extra cost of the first pop_front() is covered by the higher
- /// amortized cost of insert(), which is the real governing factor in
- /// how costly the first pop_front() will be.
- void consolidate();
-
- /// The node \p lhs is removed from the root list and becomes a subtree
- /// of node \p rhs.
- void link(internal::fibonacci_heap_node<P,T> *lhs,
- internal::fibonacci_heap_node<P,T> *rhs);
-
- void add_to_root_list(internal::fibonacci_heap_node<P,T> *);
-
- /// Remove node \p lhs from the child list of its parent node \p rhs.
- void cut(internal::fibonacci_heap_node<P,T> *lhs,
- internal::fibonacci_heap_node<P,T> *rhs);
-
- /// Cuts each node in parent list, putting successive ancestor nodes on
- /// the root list until we either arrive at the root list or until we
- /// find an ancestor that is unmarked. When a mark is set (which only
- /// happens during a cascading cut), it means that one child subtree has
- /// been lost; if a second subtree is lost later during another
- /// cascading cut, then we move the node to the root list so that it
- /// can be re-balanced on the next consolidate.
- void cascading_cut(internal::fibonacci_heap_node<P,T> *);
-
- /// Clear the heap but do *NOT* delete elements.
- void soft_clear_();
-
- /// FIXME: ugly but we need to be able to soft_clear() the heap in the
- /// copy constructor... Any idea how to do without that?
- mutable internal::fibonacci_heap_node<P,T> *min_root;
- mutable long num_nodes;
- mutable long num_trees;
- mutable long num_marked_nodes;
-
- };
-
-
- template <typename P, typename T>
- std::ostream&
- operator<<(std::ostream& cout, const fibonacci_heap<P,T>& heap);
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-
- namespace internal
- {
-
-
- /*--------------------\
- | fibonacci_heap_node |
- `--------------------*/
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T>::fibonacci_heap_node()
- : left_(0), right_(0), parent_(0), child_(0),
- degree_(0), mark_(0), priority_(0)
- // FIXME: don't we want to initialize priority with literal::zero?
- {
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T>::fibonacci_heap_node(const P& priority,
- const T& new_value)
- : left_(0), right_(0), parent_(0), child_(0),
- degree_(0), mark_(0), priority_(priority), value_(new_value)
- {
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T>::~fibonacci_heap_node()
- {
- }
-
-
- template <typename P, typename T>
- inline
- const T&
- fibonacci_heap_node<P,T>::value() const
- {
- return value_;
- }
-
-
- template <typename P, typename T>
- inline
- const P&
- fibonacci_heap_node<P,T>::priority() const
- {
- return priority_;
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T> *
- fibonacci_heap_node<P,T>::left() const
- {
- return left_;
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T> *
- fibonacci_heap_node<P,T>::right() const
- {
- return right_;
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T> *
- fibonacci_heap_node<P,T>::parent() const
- {
- return parent_;
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap_node<P,T> *
- fibonacci_heap_node<P,T>::child() const
- {
- return child_;
- }
-
-
- template <typename P, typename T>
- inline
- short
- fibonacci_heap_node<P,T>::degree() const
- {
- return degree_;
- }
-
-
- template <typename P, typename T>
- inline
- short
- fibonacci_heap_node<P,T>::mark() const
- {
- return mark_;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_value(const T& value)
- {
- value_ = value;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_left(fibonacci_heap_node<P,T> *node)
- {
- left_ = node;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_right(fibonacci_heap_node<P,T> *node)
- {
- right_ = node;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_parent(fibonacci_heap_node<P,T> *node)
- {
- parent_ = node;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_child(fibonacci_heap_node<P,T> *node)
- {
- child_ = node;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_degree(short degree)
- {
- degree_ = degree;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap_node<P,T>::set_mark(short mark)
- {
- mark_ = mark;
- }
-
-
- template <typename P, typename T>
- inline
- void fibonacci_heap_node<P,T>::operator=(fibonacci_heap_node<P,T>& rhs)
- {
- priority_ = rhs.priority();
- value_ = rhs.value();
- }
-
-
- template <typename P, typename T>
- inline
- bool
- fibonacci_heap_node<P,T>::operator==(fibonacci_heap_node<P,T>& rhs)
- {
- return priority_ == rhs.priority() && value_ == rhs.value();
- }
-
-
- template <typename P, typename T>
- inline
- bool
- fibonacci_heap_node<P,T>::operator<(fibonacci_heap_node<P,T>& rhs)
- {
- return util::ord_strict(priority_, rhs.priority())
- || (priority_ == rhs.priority() && util::ord_strict(value_, rhs.value()));
- }
-
-
- template <typename P, typename T>
- inline
- void fibonacci_heap_node<P,T>::print_() const
- {
- std::cout << value_ << " (" << priority_ << ")";
- }
-
-
- } // end of namespace mln::util::internal
-
-
-
- /*---------------\
- | fibonacci_heap |
- `---------------*/
-
- template <typename P, typename T>
- inline
- fibonacci_heap<P,T>::fibonacci_heap()
- {
- soft_clear_();
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap<P,T>::fibonacci_heap(const fibonacci_heap<P,T>& rhs)
- : Object< fibonacci_heap<P,T> >()
- {
- min_root = rhs.min_root;
- num_nodes = rhs.num_nodes;
- num_trees = rhs.num_trees;
- num_marked_nodes = rhs.num_marked_nodes;
-
-// rhs is const, we cannot call that method.
-// rhs.soft_clear_();
- rhs.min_root = 0;
- rhs.num_nodes = 0;
- rhs.num_trees = 0;
- rhs.num_marked_nodes = 0;
- }
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap<P,T>::~fibonacci_heap()
- {
- clear();
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::push(const P& priority, const T& value)
- {
- typedef internal::fibonacci_heap_node<P,T> node_t;
- node_t *new_node = new node_t(priority, value);
-
- insert(new_node);
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::push(fibonacci_heap<P,T>& other_heap)
- {
- if (other_heap.is_empty() || &other_heap == this)
- return;
-
- if (min_root != 0)
- {
- internal::fibonacci_heap_node<P,T> *min1, *min2, *next1, *next2;
-
- // We join the two circular lists by cutting each list between its
- // min node and the node after the min. This code just pulls those
- // nodes into temporary variables so we don't get lost as changes
- // are made.
- min1 = min_root;
- min2 = other_heap.min_root;
- next1 = min1->right();
- next2 = min2->right();
-
- // To join the two circles, we join the minimum nodes to the next
- // nodes on the opposite chains. Conceptually, it looks like the way
- // two bubbles join to form one larger bubble. They meet at one point
- // of contact, then expand out to make the bigger circle.
- min1->set_right(next2);
- next2->set_left(min1);
- min2->set_right(next1);
- next1->set_left(min2);
-
- // Choose the new minimum for the heap
- if (*min2 < *min1)
- min_root = min2;
- }
- else
- min_root = other_heap.min_root;
-
- // Set the amortized analysis statistics and size of the new heap
- num_nodes += other_heap.num_nodes;
- num_marked_nodes += other_heap.num_marked_nodes;
- num_trees += other_heap.num_trees;
-
- // Complete the union by setting the other heap to emptiness
- other_heap.soft_clear_();
-
- mln_postcondition(other_heap.is_empty());
- }
-
-
- template <typename P, typename T>
- inline
- const T&
- fibonacci_heap<P,T>::front() const
- {
- return min_root->value();
- }
-
-
- template <typename P, typename T>
- inline
- T
- fibonacci_heap<P,T>::pop_front()
- {
- mln_precondition(is_valid());
- mln_precondition(!is_empty());
-
- internal::fibonacci_heap_node<P,T> *result = min_root;
- fibonacci_heap<P,T> *child_heap = 0;
-
- // Remove minimum node and set min_root to next node
- min_root = result->right();
- result->right()->set_left(result->left());
- result->left()->set_right(result->right());
- result->set_left(0);
- result->set_right(0);
-
- --num_nodes;
- if (result->mark())
- {
- --num_marked_nodes;
- result->set_mark(0);
- }
- result->set_degree(0);
-
- // Attach child list of minimum node to the root list of the heap
- // If there is no child list, then do no work
- if (result->child() == 0)
- {
- if (min_root == result)
- min_root = 0;
- }
-
- // If min_root==result then there was only one root tree, so the
- // root list is simply the child list of that node (which is
- // 0 if this is the last node in the list)
- else if (min_root == result)
- min_root = result->child();
-
- // If min_root is different, then the child list is pushed into a
- // new temporary heap, which is then merged by union() onto the
- // root list of this heap.
- else
- {
- child_heap = new fibonacci_heap<P,T>();
- child_heap->min_root = result->child();
- }
-
- // Complete the disassociation of the result node from the heap
- if (result->child() != 0)
- result->child()->set_parent(0);
- result->set_child(0);
- result->set_parent(0);
-
- // If there was a child list, then we now merge it with the
- // rest of the root list
- if (child_heap)
- {
- push(*child_heap);
- delete child_heap;
- }
-
- // Consolidate heap to find new minimum and do reorganize work
- if (min_root != 0)
- consolidate();
-
- // Return the minimum node, which is now disassociated with the heap
- // It has left, right, parent, child, mark and degree cleared.
- T val = result->value();
- delete result;
-
- return val;
- }
-
-
- template <typename P, typename T>
- inline
- int
- fibonacci_heap<P,T>::decrease_key(internal::fibonacci_heap_node<P,T> *node,
- internal::fibonacci_heap_node<P,T>& key)
- {
- internal::fibonacci_heap_node<P,T> *parent;
-
- if (node == 0 || *node < key)
- return -1;
-
- *node = key;
-
- parent = node->parent();
- if (parent != 0 && *node < *parent)
- {
- cut(node, parent);
- cascading_cut(parent);
- }
-
- if (*node < *min_root)
- min_root = node;
-
- return 0;
- }
-
-
- template <typename P, typename T>
- inline
- int
- fibonacci_heap<P,T>::remove(internal::fibonacci_heap_node<P,T> *node)
- {
- internal::fibonacci_heap_node<P,T> temp;
- int result;
-
- if (node == 0)
- return -1;
-
- result = decrease_key(node, temp);
-
- if (result == 0)
- if (pop_front() == 0)
- result = -1;
-
- if (result == 0)
- delete node;
-
- return result;
- }
-
-
- template <typename P, typename T>
- inline
- bool
- fibonacci_heap<P,T>::is_empty() const
- {
- return min_root == 0;
- }
-
-
- template <typename P, typename T>
- inline
- bool
- fibonacci_heap<P,T>::is_valid() const
- {
- return min_root != 0;
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::clear()
- {
- while (min_root != 0)
- pop_front();
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::soft_clear_()
- {
- min_root = 0;
- num_nodes = 0;
- num_trees = 0;
- num_marked_nodes = 0;
- }
-
-
- template <typename P, typename T>
- inline
- unsigned
- fibonacci_heap<P,T>::nelements() const
- {
- return num_nodes;
- };
-
-
- template <typename P, typename T>
- inline
- fibonacci_heap<P,T>&
- fibonacci_heap<P,T>::operator=(fibonacci_heap<P,T>& rhs)
- {
- if (&rhs != this)
- {
- min_root = rhs.min_root;
- num_nodes = rhs.num_nodes;
- num_trees = rhs.num_trees;
- num_marked_nodes = rhs.num_marked_nodes;
- rhs.soft_clear_();
- }
- return *this;
- }
-
-
- template <typename P, typename T>
- std::ostream&
- fibonacci_heap<P,T>::print_(std::ostream& cout,
- internal::fibonacci_heap_node<P,T> *tree,
- internal::fibonacci_heap_node<P,T> *parent) const
- {
- internal::fibonacci_heap_node<P,T>* temp = 0;
-
- if (tree == 0)
- tree = min_root;
-
- temp = tree;
- if (temp != 0)
- {
- do {
- if (temp->left() == 0)
- cout << "(left is 0)";
- temp->print_();
- if (temp->parent() != parent)
- cout << "(parent is incorrect)";
- if (temp->right() == 0)
- cout << "(right is 0)";
- else if (temp->right()->left() != temp)
- cout << "(Error in left link left) ->";
- else
- cout << " <-> ";
-
- temp = temp->right();
-
- } while (temp != 0 && temp != tree);
- }
- else
- cout << " <empty>" << std::endl;
- cout << std::endl;
-
- temp = tree;
- if (temp != 0)
- {
- do {
- cout << "children of " << temp->value() << ": ";
- if (temp->child() == 0)
- cout << "NONE" << std::endl;
- else print_(cout, temp->child(), temp);
- temp = temp->right();
- } while (temp!=0 && temp != tree);
- }
-
- return cout;
- }
-
-
- template <typename P, typename T>
- inline
- void fibonacci_heap<P,T>::consolidate()
- {
- internal::fibonacci_heap_node<P,T> *x, *y, *w;
- internal::fibonacci_heap_node<P,T> *a[1 + 8 * sizeof (long)]; // 1+lg(n)
- short dn = 1 + 8 * sizeof (long);
-
- // Initialize the consolidation detection array
- for (int i = 0; i < dn; ++i)
- a[i] = 0;
-
- // We need to loop through all elements on root list.
- // When a collision of degree is found, the two trees
- // are consolidated in favor of the one with the lesser
- // element key value. We first need to break the circle
- // so that we can have a stopping condition (we can't go
- // around until we reach the tree we started with
- // because all root trees are subject to becoming a
- // child during the consolidation).
- min_root->left()->set_right(0);
- min_root->set_left(0);
- w = min_root;
-
- short d;
- do {
- x = w;
- d = x->degree();
- w = w->right();
-
- // We need another loop here because the consolidated result
- // may collide with another large tree on the root list.
- while (a[d] != 0)
- {
- y = a[d];
- if (*y < *x)
- exchange(x, y);
- if (w == y) w = y->right();
- link(y, x);
- a[d] = 0;
- ++d;
- }
- a[d] = x;
-
- } while (w != 0);
-
- // Now we rebuild the root list, find the new minimum,
- // set all root list nodes' parent pointers to 0 and
- // count the number of subtrees.
- min_root = 0;
- num_trees = 0;
- for (int i = 0; i < dn; ++i)
- if (a[i] != 0)
- add_to_root_list(a[i]);
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::link(internal::fibonacci_heap_node<P,T> *y,
- internal::fibonacci_heap_node<P,T> *x)
- {
- // Remove node y from root list
- if (y->right() != 0)
- y->right()->set_left(y->left());
- if (y->left() != 0)
- y->left()->set_right(y->right());
- --num_trees;
-
- // Make node y a singleton circular list with a parent of x
- y->set_left(y);
- y->set_right(y);
- y->set_parent(x);
-
- // If node x has no children, then list y is its new child list
- if (x->child() == 0)
- x->set_child(y);
-
- // Otherwise, node y must be added to node x's child list
- else
- {
- y->set_left(x->child());
- y->set_right(x->child()->right());
- x->child()->set_right(y);
- y->right()->set_left(y);
- }
-
- // Increase the degree of node x because it's now a bigger tree
- x->set_degree(x->degree() + 1);
-
- // node y has just been made a child, so clear its mark
- if (y->mark())
- --num_marked_nodes;
- y->set_mark(0);
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::add_to_root_list(internal::fibonacci_heap_node<P,T> *x)
- {
- if (x->mark())
- --num_marked_nodes;
- x->set_mark(0);
-
- --num_nodes;
- insert(x);
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::cut(internal::fibonacci_heap_node<P,T> *x,
- internal::fibonacci_heap_node<P,T> *y)
- {
- if (y->child() == x)
- y->child() = x->right();
- if (y->child() == x)
- y->child() = 0;
-
- y->set_degree(y->degree() - 1);
-
- x->left()->right() = x->right();
- x->right()->left() = x->left();
-
- add_to_root_list(x);
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::cascading_cut(internal::fibonacci_heap_node<P,T> *y)
- {
- internal::fibonacci_heap_node<P,T> *z = y->parent();
-
- while (z != 0)
- {
- if (y->mark() == 0)
- {
- y->mark() = 1;
- ++num_marked_nodes;
- z = 0;
- }
- else
- {
- cut(y, z);
- y = z;
- z = y->parent();
- }
- }
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::insert(internal::fibonacci_heap_node<P,T> *node)
- {
- if (node == 0)
- return;
-
- // If the heap is currently empty, then new node becomes singleton
- // circular root list
- if (min_root == 0)
- {
- min_root = node;
- node->set_left(node);
- node->set_right(node);
- }
- else
- {
- // Pointers from node set to insert between min_root and
- // min_root->right()
- node->set_right(min_root->right());
- node->set_left(min_root);
-
- // Set Pointers to node
- node->left()->set_right(node);
- node->right()->set_left(node);
-
- // The new node becomes new min_root if it is less than current
- // min_root
- if (*node < *min_root)
- min_root = node;
- }
-
- // We have one more node in the heap, and it is a tree on the root list
- ++num_nodes;
- ++num_trees;
- node->set_parent(0);
- }
-
-
- template <typename P, typename T>
- inline
- void
- fibonacci_heap<P,T>::exchange(internal::fibonacci_heap_node<P,T>*& n1,
- internal::fibonacci_heap_node<P,T>*& n2)
- {
- internal::fibonacci_heap_node<P,T> *temp;
-
- temp = n1;
- n1 = n2;
- n2 = temp;
- }
-
-
- template <typename P, typename T>
- std::ostream&
- operator<<(std::ostream& cout, const fibonacci_heap<P,T>& heap)
- {
- return heap.print_(cout);
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
-
-
- } // end of namespace mln::util
-
-} // end of namespace mln
-
-#endif // ! MLN_UTIL_FIBONACCI_HEAP_HH
+// Copyright (C) 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+//
+//***************************************************************************
+// The Fibonacci heap implementation is Copyright (c) 1996 by John Boyer
+//
+// Once this Fibonacci heap implementation (the software) has been published
+// by Dr. Dobb's Journal, permission to use and distribute the software is
+// granted provided that this copyright notice remains in the source and
+// and the author (John Boyer) is acknowledged in works that use this program.
+//
+// Every effort has been made to ensure that this implementation is free of
+// errors. Nonetheless, the author (John Boyer) assumes no liability regarding
+// your use of this software.
+//
+// The author would also be very glad to hear from anyone who uses the
+// software or has any feedback about it.
+// Email: jboyer(a)gulf.csc.uvic.ca
+//***************************************************************************
+
+
+#ifndef MLN_UTIL_FIBONACCI_HEAP_HH
+# define MLN_UTIL_FIBONACCI_HEAP_HH
+
+
+# include <iostream>
+# include <mln/core/concept/object.hh>
+# include <mln/util/ord.hh>
+
+
+
+namespace mln
+{
+
+ namespace util
+ {
+
+
+ namespace internal
+ {
+
+ /*--------------------------\
+ | Fibonacci Heap node Class |
+ `--------------------------*/
+
+ template <typename P, typename T>
+ class fibonacci_heap_node
+ {
+
+ public:
+ /// Default constructor.
+ fibonacci_heap_node();
+
+ /// Construct a new node with \p value as value.
+ fibonacci_heap_node(const P& priority, const T& value);
+
+ ~fibonacci_heap_node();
+
+ /// Return the node value.
+ const T& value() const;
+
+ const P& priority() const;
+
+ fibonacci_heap_node<P,T> *left() const;
+ fibonacci_heap_node<P,T> *right() const;
+ fibonacci_heap_node<P,T> *parent() const;
+ fibonacci_heap_node<P,T> *child() const;
+
+ short degree() const;
+
+ short mark() const;
+
+
+ void set_value(const T&);
+ void set_left(fibonacci_heap_node<P,T> *node);
+ void set_right(fibonacci_heap_node<P,T> *node);
+ void set_parent(fibonacci_heap_node<P,T> *node);
+ void set_child(fibonacci_heap_node<P,T> *node);
+ void set_degree(short degree);
+ void set_mark(short mark);
+
+ void operator=(fibonacci_heap_node<P,T>& rhs);
+ bool operator==(fibonacci_heap_node<P,T>& rhs);
+ bool operator<(fibonacci_heap_node<P,T>& rhs);
+
+ void print_() const;
+
+
+ private:
+
+ fibonacci_heap_node<P,T> *left_;
+ fibonacci_heap_node<P,T> *right_;
+ fibonacci_heap_node<P,T> *parent_;
+ fibonacci_heap_node<P,T> *child_;
+ short degree_;
+ short mark_;
+ P priority_;
+ T value_;
+ };
+
+ } // end of namespace mln::util::internal
+
+
+
+ /*---------------------\
+ | Fibonacci Heap Class |
+ `---------------------*/
+
+ template <typename P, typename T>
+ class fibonacci_heap : public Object< fibonacci_heap<P,T> >
+ {
+ public:
+
+ typedef T element;
+
+ /// Default constructor
+ fibonacci_heap();
+
+ /// Copy constructor
+ /// Be ware that once this heap is constructed, the argument \p node
+ /// is cleared and all its elements are part of this new heap.
+ fibonacci_heap(const fibonacci_heap<P,T>& node);
+
+ ~fibonacci_heap();
+
+ /// Push a new element in the heap.
+ /// \sa insert
+ void push(const P& priority, const T& value);
+
+ /// Take \p other_heap's elements and insert them in this heap.
+ /// After this call \p other_heap is cleared.
+ void push(fibonacci_heap<P,T>& other_heap);
+
+ /// Return the minimum value in the heap.
+ const T& front() const;
+
+ /// Return and remove the minimum value in the heap.
+ T pop_front();
+
+ /// Is it empty?
+ bool is_empty() const;
+
+ /// return false if it is empty.
+ bool is_valid() const;
+
+ /// Return the number of elements.
+ unsigned nelements() const;
+
+ /// Clear all elements in the heap and make the heap empty.
+ void clear();
+
+ /// Assignment operator.
+ /// Be ware that this operator do *not* copy the data from \p rhs to this heap.
+ /// It moves all elements which means that afterwards, \p rhs is
+ /// is cleared and all its elements are part of this new heap.
+ fibonacci_heap<P,T>& operator=(fibonacci_heap<P,T>& rhs);
+
+
+
+ std::ostream& print_(std::ostream& cout,
+ internal::fibonacci_heap_node<P,T> *tree = 0,
+ internal::fibonacci_heap_node<P,T> *parent = 0) const;
+
+ private:
+
+ // Internal functions that help to implement the Standard Operations
+
+
+ /// Allow to change a node value.
+ /// FIXME: cannot use that function efficiently except by passing the
+ /// node pointer. Any idea?
+ /// FIXME: may be part of the public interface.
+ int decrease_key(internal::fibonacci_heap_node<P,T> *node,
+ internal::fibonacci_heap_node<P,T>& key);
+
+ /// Remove node \p node from the child list of its parent node.
+ /// FIXME: cannot use that function efficiently except by passing the
+ /// node pointer. Any idea?
+ /// FIXME: may be part of the public interface.
+ int remove(internal::fibonacci_heap_node<P,T> *node);
+
+ /// Insert a new node \p node in the heap.
+ void insert(internal::fibonacci_heap_node<P,T> *node);
+
+ /// Swap the two given nodes.
+ void exchange(internal::fibonacci_heap_node<P,T>*& lhs,
+ internal::fibonacci_heap_node<P,T>*& rhs);
+
+ /// Internal function that reorganizes heap as part of an pop_front().
+ /// We must find new minimum in heap, which could be anywhere along the
+ /// root list. The search could be O(n) since all nodes could be on
+ /// the root list. So, we reorganize the tree into more of a binomial
+ /// forest structure, and then find the new minimum on the consolidated
+ /// O(lg n) sized root list, and in the process set each Parent pointer
+ /// to 0, and count the number of resulting subtrees.
+ ///
+ /// Note that after a list of n inserts, there will be n nodes on the
+ /// root list, so the first pop_front() will be O(n) regardless of
+ /// whether or not we consolidate. However, the consolidation causes
+ /// subsequent pop_front() operations to be O(lg n). Furthermore,
+ /// the extra cost of the first pop_front() is covered by the higher
+ /// amortized cost of insert(), which is the real governing factor in
+ /// how costly the first pop_front() will be.
+ void consolidate();
+
+ /// The node \p lhs is removed from the root list and becomes a subtree
+ /// of node \p rhs.
+ void link(internal::fibonacci_heap_node<P,T> *lhs,
+ internal::fibonacci_heap_node<P,T> *rhs);
+
+ void add_to_root_list(internal::fibonacci_heap_node<P,T> *);
+
+ /// Remove node \p lhs from the child list of its parent node \p rhs.
+ void cut(internal::fibonacci_heap_node<P,T> *lhs,
+ internal::fibonacci_heap_node<P,T> *rhs);
+
+ /// Cuts each node in parent list, putting successive ancestor nodes on
+ /// the root list until we either arrive at the root list or until we
+ /// find an ancestor that is unmarked. When a mark is set (which only
+ /// happens during a cascading cut), it means that one child subtree has
+ /// been lost; if a second subtree is lost later during another
+ /// cascading cut, then we move the node to the root list so that it
+ /// can be re-balanced on the next consolidate.
+ void cascading_cut(internal::fibonacci_heap_node<P,T> *);
+
+ /// Clear the heap but do *NOT* delete elements.
+ void soft_clear_();
+
+ /// FIXME: ugly but we need to be able to soft_clear() the heap in the
+ /// copy constructor... Any idea how to do without that?
+ mutable internal::fibonacci_heap_node<P,T> *min_root;
+ mutable long num_nodes;
+ mutable long num_trees;
+ mutable long num_marked_nodes;
+
+ };
+
+
+ template <typename P, typename T>
+ std::ostream&
+ operator<<(std::ostream& cout, const fibonacci_heap<P,T>& heap);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+
+ /*--------------------\
+ | fibonacci_heap_node |
+ `--------------------*/
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T>::fibonacci_heap_node()
+ : left_(0), right_(0), parent_(0), child_(0),
+ degree_(0), mark_(0), priority_(0)
+ // FIXME: don't we want to initialize priority with literal::zero?
+ {
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T>::fibonacci_heap_node(const P& priority,
+ const T& new_value)
+ : left_(0), right_(0), parent_(0), child_(0),
+ degree_(0), mark_(0), priority_(priority), value_(new_value)
+ {
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T>::~fibonacci_heap_node()
+ {
+ }
+
+
+ template <typename P, typename T>
+ inline
+ const T&
+ fibonacci_heap_node<P,T>::value() const
+ {
+ return value_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ const P&
+ fibonacci_heap_node<P,T>::priority() const
+ {
+ return priority_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T> *
+ fibonacci_heap_node<P,T>::left() const
+ {
+ return left_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T> *
+ fibonacci_heap_node<P,T>::right() const
+ {
+ return right_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T> *
+ fibonacci_heap_node<P,T>::parent() const
+ {
+ return parent_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap_node<P,T> *
+ fibonacci_heap_node<P,T>::child() const
+ {
+ return child_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ short
+ fibonacci_heap_node<P,T>::degree() const
+ {
+ return degree_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ short
+ fibonacci_heap_node<P,T>::mark() const
+ {
+ return mark_;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_value(const T& value)
+ {
+ value_ = value;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_left(fibonacci_heap_node<P,T> *node)
+ {
+ left_ = node;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_right(fibonacci_heap_node<P,T> *node)
+ {
+ right_ = node;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_parent(fibonacci_heap_node<P,T> *node)
+ {
+ parent_ = node;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_child(fibonacci_heap_node<P,T> *node)
+ {
+ child_ = node;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_degree(short degree)
+ {
+ degree_ = degree;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap_node<P,T>::set_mark(short mark)
+ {
+ mark_ = mark;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void fibonacci_heap_node<P,T>::operator=(fibonacci_heap_node<P,T>& rhs)
+ {
+ priority_ = rhs.priority();
+ value_ = rhs.value();
+ }
+
+
+ template <typename P, typename T>
+ inline
+ bool
+ fibonacci_heap_node<P,T>::operator==(fibonacci_heap_node<P,T>& rhs)
+ {
+ return priority_ == rhs.priority() && value_ == rhs.value();
+ }
+
+
+ template <typename P, typename T>
+ inline
+ bool
+ fibonacci_heap_node<P,T>::operator<(fibonacci_heap_node<P,T>& rhs)
+ {
+ return util::ord_strict(priority_, rhs.priority())
+ || (priority_ == rhs.priority() && util::ord_strict(value_, rhs.value()));
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void fibonacci_heap_node<P,T>::print_() const
+ {
+ std::cout << value_ << " (" << priority_ << ")";
+ }
+
+
+ } // end of namespace mln::util::internal
+
+
+
+ /*---------------\
+ | fibonacci_heap |
+ `---------------*/
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap<P,T>::fibonacci_heap()
+ {
+ soft_clear_();
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap<P,T>::fibonacci_heap(const fibonacci_heap<P,T>& rhs)
+ : Object< fibonacci_heap<P,T> >()
+ {
+ min_root = rhs.min_root;
+ num_nodes = rhs.num_nodes;
+ num_trees = rhs.num_trees;
+ num_marked_nodes = rhs.num_marked_nodes;
+
+// rhs is const, we cannot call that method.
+// rhs.soft_clear_();
+ rhs.min_root = 0;
+ rhs.num_nodes = 0;
+ rhs.num_trees = 0;
+ rhs.num_marked_nodes = 0;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap<P,T>::~fibonacci_heap()
+ {
+ clear();
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::push(const P& priority, const T& value)
+ {
+ typedef internal::fibonacci_heap_node<P,T> node_t;
+ node_t *new_node = new node_t(priority, value);
+
+ insert(new_node);
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::push(fibonacci_heap<P,T>& other_heap)
+ {
+ if (other_heap.is_empty() || &other_heap == this)
+ return;
+
+ if (min_root != 0)
+ {
+ internal::fibonacci_heap_node<P,T> *min1, *min2, *next1, *next2;
+
+ // We join the two circular lists by cutting each list between its
+ // min node and the node after the min. This code just pulls those
+ // nodes into temporary variables so we don't get lost as changes
+ // are made.
+ min1 = min_root;
+ min2 = other_heap.min_root;
+ next1 = min1->right();
+ next2 = min2->right();
+
+ // To join the two circles, we join the minimum nodes to the next
+ // nodes on the opposite chains. Conceptually, it looks like the way
+ // two bubbles join to form one larger bubble. They meet at one point
+ // of contact, then expand out to make the bigger circle.
+ min1->set_right(next2);
+ next2->set_left(min1);
+ min2->set_right(next1);
+ next1->set_left(min2);
+
+ // Choose the new minimum for the heap
+ if (*min2 < *min1)
+ min_root = min2;
+ }
+ else
+ min_root = other_heap.min_root;
+
+ // Set the amortized analysis statistics and size of the new heap
+ num_nodes += other_heap.num_nodes;
+ num_marked_nodes += other_heap.num_marked_nodes;
+ num_trees += other_heap.num_trees;
+
+ // Complete the union by setting the other heap to emptiness
+ other_heap.soft_clear_();
+
+ mln_postcondition(other_heap.is_empty());
+ }
+
+
+ template <typename P, typename T>
+ inline
+ const T&
+ fibonacci_heap<P,T>::front() const
+ {
+ return min_root->value();
+ }
+
+
+ template <typename P, typename T>
+ inline
+ T
+ fibonacci_heap<P,T>::pop_front()
+ {
+ mln_precondition(is_valid());
+ mln_precondition(!is_empty());
+
+ internal::fibonacci_heap_node<P,T> *result = min_root;
+ fibonacci_heap<P,T> *child_heap = 0;
+
+ // Remove minimum node and set min_root to next node
+ min_root = result->right();
+ result->right()->set_left(result->left());
+ result->left()->set_right(result->right());
+ result->set_left(0);
+ result->set_right(0);
+
+ --num_nodes;
+ if (result->mark())
+ {
+ --num_marked_nodes;
+ result->set_mark(0);
+ }
+ result->set_degree(0);
+
+ // Attach child list of minimum node to the root list of the heap
+ // If there is no child list, then do no work
+ if (result->child() == 0)
+ {
+ if (min_root == result)
+ min_root = 0;
+ }
+
+ // If min_root==result then there was only one root tree, so the
+ // root list is simply the child list of that node (which is
+ // 0 if this is the last node in the list)
+ else if (min_root == result)
+ min_root = result->child();
+
+ // If min_root is different, then the child list is pushed into a
+ // new temporary heap, which is then merged by union() onto the
+ // root list of this heap.
+ else
+ {
+ child_heap = new fibonacci_heap<P,T>();
+ child_heap->min_root = result->child();
+ }
+
+ // Complete the disassociation of the result node from the heap
+ if (result->child() != 0)
+ result->child()->set_parent(0);
+ result->set_child(0);
+ result->set_parent(0);
+
+ // If there was a child list, then we now merge it with the
+ // rest of the root list
+ if (child_heap)
+ {
+ push(*child_heap);
+ delete child_heap;
+ }
+
+ // Consolidate heap to find new minimum and do reorganize work
+ if (min_root != 0)
+ consolidate();
+
+ // Return the minimum node, which is now disassociated with the heap
+ // It has left, right, parent, child, mark and degree cleared.
+ T val = result->value();
+ delete result;
+
+ return val;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ int
+ fibonacci_heap<P,T>::decrease_key(internal::fibonacci_heap_node<P,T> *node,
+ internal::fibonacci_heap_node<P,T>& key)
+ {
+ internal::fibonacci_heap_node<P,T> *parent;
+
+ if (node == 0 || *node < key)
+ return -1;
+
+ *node = key;
+
+ parent = node->parent();
+ if (parent != 0 && *node < *parent)
+ {
+ cut(node, parent);
+ cascading_cut(parent);
+ }
+
+ if (*node < *min_root)
+ min_root = node;
+
+ return 0;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ int
+ fibonacci_heap<P,T>::remove(internal::fibonacci_heap_node<P,T> *node)
+ {
+ internal::fibonacci_heap_node<P,T> temp;
+ int result;
+
+ if (node == 0)
+ return -1;
+
+ result = decrease_key(node, temp);
+
+ if (result == 0)
+ if (pop_front() == 0)
+ result = -1;
+
+ if (result == 0)
+ delete node;
+
+ return result;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ bool
+ fibonacci_heap<P,T>::is_empty() const
+ {
+ return min_root == 0;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ bool
+ fibonacci_heap<P,T>::is_valid() const
+ {
+ return min_root != 0;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::clear()
+ {
+ while (min_root != 0)
+ pop_front();
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::soft_clear_()
+ {
+ min_root = 0;
+ num_nodes = 0;
+ num_trees = 0;
+ num_marked_nodes = 0;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ unsigned
+ fibonacci_heap<P,T>::nelements() const
+ {
+ return num_nodes;
+ };
+
+
+ template <typename P, typename T>
+ inline
+ fibonacci_heap<P,T>&
+ fibonacci_heap<P,T>::operator=(fibonacci_heap<P,T>& rhs)
+ {
+ if (&rhs != this)
+ {
+ min_root = rhs.min_root;
+ num_nodes = rhs.num_nodes;
+ num_trees = rhs.num_trees;
+ num_marked_nodes = rhs.num_marked_nodes;
+ rhs.soft_clear_();
+ }
+ return *this;
+ }
+
+
+ template <typename P, typename T>
+ std::ostream&
+ fibonacci_heap<P,T>::print_(std::ostream& cout,
+ internal::fibonacci_heap_node<P,T> *tree,
+ internal::fibonacci_heap_node<P,T> *parent) const
+ {
+ internal::fibonacci_heap_node<P,T>* temp = 0;
+
+ if (tree == 0)
+ tree = min_root;
+
+ temp = tree;
+ if (temp != 0)
+ {
+ do {
+ if (temp->left() == 0)
+ cout << "(left is 0)";
+ temp->print_();
+ if (temp->parent() != parent)
+ cout << "(parent is incorrect)";
+ if (temp->right() == 0)
+ cout << "(right is 0)";
+ else if (temp->right()->left() != temp)
+ cout << "(Error in left link left) ->";
+ else
+ cout << " <-> ";
+
+ temp = temp->right();
+
+ } while (temp != 0 && temp != tree);
+ }
+ else
+ cout << " <empty>" << std::endl;
+ cout << std::endl;
+
+ temp = tree;
+ if (temp != 0)
+ {
+ do {
+ cout << "children of " << temp->value() << ": ";
+ if (temp->child() == 0)
+ cout << "NONE" << std::endl;
+ else print_(cout, temp->child(), temp);
+ temp = temp->right();
+ } while (temp!=0 && temp != tree);
+ }
+
+ return cout;
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void fibonacci_heap<P,T>::consolidate()
+ {
+ internal::fibonacci_heap_node<P,T> *x, *y, *w;
+ internal::fibonacci_heap_node<P,T> *a[1 + 8 * sizeof (long)]; // 1+lg(n)
+ short dn = 1 + 8 * sizeof (long);
+
+ // Initialize the consolidation detection array
+ for (int i = 0; i < dn; ++i)
+ a[i] = 0;
+
+ // We need to loop through all elements on root list.
+ // When a collision of degree is found, the two trees
+ // are consolidated in favor of the one with the lesser
+ // element key value. We first need to break the circle
+ // so that we can have a stopping condition (we can't go
+ // around until we reach the tree we started with
+ // because all root trees are subject to becoming a
+ // child during the consolidation).
+ min_root->left()->set_right(0);
+ min_root->set_left(0);
+ w = min_root;
+
+ short d;
+ do {
+ x = w;
+ d = x->degree();
+ w = w->right();
+
+ // We need another loop here because the consolidated result
+ // may collide with another large tree on the root list.
+ while (a[d] != 0)
+ {
+ y = a[d];
+ if (*y < *x)
+ exchange(x, y);
+ if (w == y) w = y->right();
+ link(y, x);
+ a[d] = 0;
+ ++d;
+ }
+ a[d] = x;
+
+ } while (w != 0);
+
+ // Now we rebuild the root list, find the new minimum,
+ // set all root list nodes' parent pointers to 0 and
+ // count the number of subtrees.
+ min_root = 0;
+ num_trees = 0;
+ for (int i = 0; i < dn; ++i)
+ if (a[i] != 0)
+ add_to_root_list(a[i]);
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::link(internal::fibonacci_heap_node<P,T> *y,
+ internal::fibonacci_heap_node<P,T> *x)
+ {
+ // Remove node y from root list
+ if (y->right() != 0)
+ y->right()->set_left(y->left());
+ if (y->left() != 0)
+ y->left()->set_right(y->right());
+ --num_trees;
+
+ // Make node y a singleton circular list with a parent of x
+ y->set_left(y);
+ y->set_right(y);
+ y->set_parent(x);
+
+ // If node x has no children, then list y is its new child list
+ if (x->child() == 0)
+ x->set_child(y);
+
+ // Otherwise, node y must be added to node x's child list
+ else
+ {
+ y->set_left(x->child());
+ y->set_right(x->child()->right());
+ x->child()->set_right(y);
+ y->right()->set_left(y);
+ }
+
+ // Increase the degree of node x because it's now a bigger tree
+ x->set_degree(x->degree() + 1);
+
+ // node y has just been made a child, so clear its mark
+ if (y->mark())
+ --num_marked_nodes;
+ y->set_mark(0);
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::add_to_root_list(internal::fibonacci_heap_node<P,T> *x)
+ {
+ if (x->mark())
+ --num_marked_nodes;
+ x->set_mark(0);
+
+ --num_nodes;
+ insert(x);
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::cut(internal::fibonacci_heap_node<P,T> *x,
+ internal::fibonacci_heap_node<P,T> *y)
+ {
+ if (y->child() == x)
+ y->child() = x->right();
+ if (y->child() == x)
+ y->child() = 0;
+
+ y->set_degree(y->degree() - 1);
+
+ x->left()->right() = x->right();
+ x->right()->left() = x->left();
+
+ add_to_root_list(x);
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::cascading_cut(internal::fibonacci_heap_node<P,T> *y)
+ {
+ internal::fibonacci_heap_node<P,T> *z = y->parent();
+
+ while (z != 0)
+ {
+ if (y->mark() == 0)
+ {
+ y->mark() = 1;
+ ++num_marked_nodes;
+ z = 0;
+ }
+ else
+ {
+ cut(y, z);
+ y = z;
+ z = y->parent();
+ }
+ }
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::insert(internal::fibonacci_heap_node<P,T> *node)
+ {
+ if (node == 0)
+ return;
+
+ // If the heap is currently empty, then new node becomes singleton
+ // circular root list
+ if (min_root == 0)
+ {
+ min_root = node;
+ node->set_left(node);
+ node->set_right(node);
+ }
+ else
+ {
+ // Pointers from node set to insert between min_root and
+ // min_root->right()
+ node->set_right(min_root->right());
+ node->set_left(min_root);
+
+ // Set Pointers to node
+ node->left()->set_right(node);
+ node->right()->set_left(node);
+
+ // The new node becomes new min_root if it is less than current
+ // min_root
+ if (*node < *min_root)
+ min_root = node;
+ }
+
+ // We have one more node in the heap, and it is a tree on the root list
+ ++num_nodes;
+ ++num_trees;
+ node->set_parent(0);
+ }
+
+
+ template <typename P, typename T>
+ inline
+ void
+ fibonacci_heap<P,T>::exchange(internal::fibonacci_heap_node<P,T>*& n1,
+ internal::fibonacci_heap_node<P,T>*& n2)
+ {
+ internal::fibonacci_heap_node<P,T> *temp;
+
+ temp = n1;
+ n1 = n2;
+ n2 = temp;
+ }
+
+
+ template <typename P, typename T>
+ std::ostream&
+ operator<<(std::ostream& cout, const fibonacci_heap<P,T>& heap)
+ {
+ return heap.print_(cout);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+
+ } // end of namespace mln::util
+
+} // end of namespace mln
+
+#endif // ! MLN_UTIL_FIBONACCI_HEAP_HH
--
1.6.1.2
* apps/statues/mesh-complex-max-curv-segm.cc,
* apps/statues/mesh-complex-segm.cc,
* tests/morpho/artificial_line_graph_image_wst.cc,
* tests/morpho/lena_line_graph_image_wst2.cc:
Here.
---
milena/ChangeLog | 10 ++++++++++
milena/apps/statues/mesh-complex-max-curv-segm.cc | 2 +-
milena/apps/statues/mesh-complex-segm.cc | 2 +-
.../morpho/artificial_line_graph_image_wst.cc | 2 +-
milena/tests/morpho/lena_line_graph_image_wst2.cc | 2 +-
5 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 910aac6..f23692c 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,15 @@
2009-04-06 Roland Levillain <roland(a)lrde.epita.fr>
+ Typos in comments.
+
+ * apps/statues/mesh-complex-max-curv-segm.cc,
+ * apps/statues/mesh-complex-segm.cc,
+ * tests/morpho/artificial_line_graph_image_wst.cc,
+ * tests/morpho/lena_line_graph_image_wst2.cc:
+ Here.
+
+2009-04-06 Roland Levillain <roland(a)lrde.epita.fr>
+
Exercise apps/statues/mesh-complex-skel.
* apps/statues/test-mesh-complex-skel.in: New test.
diff --git a/milena/apps/statues/mesh-complex-max-curv-segm.cc b/milena/apps/statues/mesh-complex-max-curv-segm.cc
index e52d990..37d4fbb 100644
--- a/milena/apps/statues/mesh-complex-max-curv-segm.cc
+++ b/milena/apps/statues/mesh-complex-max-curv-segm.cc
@@ -125,7 +125,7 @@ int main(int argc, char* argv[])
| Simplification. |
`-----------------*/
- /// Adjancent edges are connected by shared polygons.
+ /// Adjacent edges are connected by shared polygons.
typedef
mln::complex_higher_dim_connected_n_face_neighborhood<D, G>
adj_edges_nbh_t;
diff --git a/milena/apps/statues/mesh-complex-segm.cc b/milena/apps/statues/mesh-complex-segm.cc
index b67d7f6..ab049fc 100644
--- a/milena/apps/statues/mesh-complex-segm.cc
+++ b/milena/apps/statues/mesh-complex-segm.cc
@@ -100,7 +100,7 @@ int main(int argc, char* argv[])
| Simplification. |
`-----------------*/
- /// Adjancent edges are connected by shared polygons.
+ /// Adjacent edges are connected by shared polygons.
typedef
mln::complex_higher_dim_connected_n_face_neighborhood<D, G>
adj_edges_nbh_t;
diff --git a/milena/tests/morpho/artificial_line_graph_image_wst.cc b/milena/tests/morpho/artificial_line_graph_image_wst.cc
index cf25180..65a31e6 100644
--- a/milena/tests/morpho/artificial_line_graph_image_wst.cc
+++ b/milena/tests/morpho/artificial_line_graph_image_wst.cc
@@ -39,7 +39,7 @@
\li create an artificial (checkboard) 2-D image ;
\li convert this 2-D image into a line graph-based one, where values
on edges are computed as the absolute value of the difference
- between the values on the vertices adjacent to the edge, so as to
+ between the values on the vertices adjacent to the edge, so as to
create a (norm of the) gradient ``between the pixels'' of the
input image;
\li perform a WST on this line graph image;
diff --git a/milena/tests/morpho/lena_line_graph_image_wst2.cc b/milena/tests/morpho/lena_line_graph_image_wst2.cc
index a7121ba..6922a83 100644
--- a/milena/tests/morpho/lena_line_graph_image_wst2.cc
+++ b/milena/tests/morpho/lena_line_graph_image_wst2.cc
@@ -39,7 +39,7 @@
\li load a 2-D, gray-level image from a PGM file;
\li convert this 2-D image into a line graph-based one, where values
on edges are computed as the absolute value of the difference
- between the values on the vertices adjacent to the edge, so as to
+ between the values on the vertices adjacent to the edge, so as to
create a (norm of the) gradient ``between the pixels'' of the
input image;
\li reduce the number of minima using an area opening (counting the
--
1.6.1.2