Olena-patches
Threads by month
- ----- 2025 -----
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
January 2013
- 7 participants
- 66 discussions
* mln/util/map.hh,
* tests/util/map.cc: New.
* tests/util/Makefile: Add new target.
---
milena/ChangeLog | 9 +
milena/mln/util/map.hh | 741 ++++++++++++++++++++
milena/tests/util/Makefile.am | 2 +
.../compute_in_inner_border.cc => util/map.cc} | 47 +-
4 files changed, 784 insertions(+), 15 deletions(-)
create mode 100644 milena/mln/util/map.hh
copy milena/tests/{data/compute_in_inner_border.cc => util/map.cc} (63%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 473f717..a6df4ca 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add util::map.
+
+ * mln/util/map.hh,
+ * tests/util/map.cc: New.
+
+ * tests/util/Makefile: Add new target.
+
+2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* mln/inner_border/remove.hh: New.
2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/milena/mln/util/map.hh b/milena/mln/util/map.hh
new file mode 100644
index 0000000..680d3e4
--- /dev/null
+++ b/milena/mln/util/map.hh
@@ -0,0 +1,741 @@
+// Copyright (C) 2012 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_MAP_HH
+# define MLN_UTIL_MAP_HH
+
+/// \file
+///
+/// Definition of mln::util::map.
+
+
+# include <map>
+# include <iostream>
+# include <algorithm>
+
+# include <mln/core/alias/box1d.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/core/concept/proxy.hh>
+# include <mln/core/concept/iterator.hh>
+
+# include <mln/fun/internal/selector.hh>
+
+# include <mln/util/ord.hh>
+
+
+namespace mln
+{
+
+ // Forward declarations.
+ namespace fun {
+ namespace i2v {
+ template <typename K, typename V> class map;
+ }
+ }
+ template <typename V> struct image1d;
+ // End of forward declarations
+
+
+ namespace util
+ {
+
+ // Forward declarations.
+ template <typename K, typename V> class map_fwd_iter;
+ template <typename K, typename V> class map_bkd_iter;
+
+
+ /// \brief A dynamic map class.
+ ///
+ /// Elements are stored by copy. Implementation is lazy.
+ ///
+ /// The parameter \c T is the element type, which shall not be
+ /// const-qualified.
+ ///
+ /// \ingroup modutil
+ //
+ template <typename K, typename V>
+ class map
+ : public mln::fun::internal::selector_from_result_<V, map<K,V> >::ret
+ {
+ public:
+
+ /// Element associated type.
+ typedef K element;
+
+ /// Returned value types.
+ /// Related to the Function_v2v concept.
+ /// @{
+ typedef V result;
+ typedef const V& ro_result;
+ typedef V& mutable_result;
+ /// @}
+
+
+ /// Iterator types
+ /// @{
+ /// Forward iterator associated type.
+ typedef map_fwd_iter<K,V> fwd_eiter;
+
+ /// Backward iterator associated type.
+ typedef map_bkd_iter<K,V> bkd_eiter;
+
+ /// Iterator associated type.
+ typedef fwd_eiter eiter;
+ /// @}
+
+
+ /// Constructors
+ /// @{
+ /// Constructor without arguments.
+ map();
+
+ /// Remove element mapped to key \p key.
+ void erase(const K& key);
+
+ /// Return the number of elements of the map.
+ unsigned nelements() const;
+
+ /// Return the number of elements of the map.
+ /// \sa nelements
+ unsigned size() const;
+
+ /// Test if the map is empty.
+ bool is_empty() const;
+
+
+ /// \brief Return the value mapped to the key \p key.
+ /// \pre i < nelements()
+ ro_result operator()(const K& key) const;
+
+ /// \brief Return the value mapped to the key \p key.
+ /// \pre i < nelements()
+ mutable_result operator()(const K& key);
+
+ /// \brief Return the value mapped to the key \p key.
+ /// \pre i < nelements()
+ ro_result operator[](const K& key) const;
+
+ /// \brief Return the value mapped to the key \p key.
+ /// \pre i < nelements()
+ mutable_result operator[](const K& key);
+
+ /// \brief Return true if \p key is in this map.
+ bool has(const K& key) const;
+
+ /// Empty the map. All elements contained in the map are
+ /// destroyed. \post is_empty() == true
+ void clear();
+
+ /// Return the corresponding std::map of elements.
+ const std::map<K,V,util::ord<K> >& std_map() const;
+
+ /// Hook to the mutable std::map of elements.
+ std::map<K,V,util::ord<K> >& hook_std_map_();
+
+ private:
+ mutable std::map<K,V,util::ord<K> > m_;
+ };
+
+
+ /// Operator<<.
+ template <typename K, typename V>
+ std::ostream& operator<<(std::ostream& ostr,
+ const map<K,V>& a);
+
+ /// Operator==
+ template <typename K, typename V>
+ bool operator==(const map<K,V>& lhs,
+ const map<K,V>& rhs);
+
+
+ // map_fwd_iter<K,V>
+
+ template <typename K, typename V>
+ class map_fwd_iter : public Proxy< map_fwd_iter<K,V> >,
+ public mln::internal::proxy_impl< const std::pair<K,V>,
+ map_fwd_iter<K,V> >
+ {
+ public:
+ typedef const std::pair<K,V> subj_t;
+
+ /// Constructors
+ /// @{
+ /// Constructor without argument.
+ map_fwd_iter();
+
+ /// Constructor from an map \p a.
+ map_fwd_iter(const map<K,V>& a);
+ /// @}
+
+ /// Change the map it iterates on to \p a.
+ void change_target(const map<K,V>& a);
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next element.
+ void next();
+
+ /// Returns true if the iterator is valid.
+ bool is_valid() const;
+
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Give the element the iterator designates.
+ const std::pair<K,V>& element() const;
+
+ // As a Proxy.
+ subj_t subj_();
+
+ /// Give the current index.
+ unsigned index_() const;
+
+ protected:
+ typename std::map<K,V,util::ord<K> >::const_iterator i_;
+ const std::map<K,V,util::ord<K> >* a_;
+ };
+
+
+
+
+ // map_bkd_iter<K,V>
+
+ template <typename K, typename V>
+ class map_bkd_iter : public Proxy< map_bkd_iter<K,V> >,
+ public mln::internal::proxy_impl< const std::pair<K,V>,
+ map_bkd_iter<K,V> >
+ {
+ public:
+ typedef const std::pair<K,V> subj_t;
+
+ /// Constructors
+ /// @{
+ /// Constructor without argument.
+ map_bkd_iter();
+
+ /// Constructor from an map \p a.
+ map_bkd_iter(const map<K,V>& a);
+ /// @}
+
+ /// Change the map it iterates on to \p a.
+ void change_target(const map<K,V>& a);
+
+ /// Start an iteration.
+ void start();
+
+ /// Go to the next element.
+ void next();
+
+ /// Returns true if the iterator is valid.
+ bool is_valid() const;
+
+ /// Invalidate the iterator.
+ void invalidate();
+
+ /// Give the element the iterator designates.
+ const std::pair<K,V>& element() const;
+
+ // As a Proxy.
+ subj_t subj_();
+
+ /// Give the current index.
+ unsigned index_() const;
+
+ protected:
+ typename std::map<K,V,util::ord<K> >::const_reverse_iterator i_;
+ const std::map<K,V,util::ord<K> >* a_;
+ };
+
+ } // end of namespace mln::util
+
+
+ namespace internal
+ {
+
+ template <typename K, typename V, typename E>
+ struct subject_impl<const util::map<K,V>, E>
+ {
+ typedef typename util::map<K,V>::ro_result ro_result;
+
+ ro_result operator()(const K& key) const;
+ ro_result operator[](const K& key) const;
+
+ unsigned nelements() const;
+ unsigned size() const;
+ bool is_empty() const;
+ const std::map<K,V,util::ord<K> > std_map() const;
+
+ private:
+ const E& exact_() const;
+ };
+
+
+ template <typename K, typename V, typename E>
+ struct subject_impl<util::map<K,V>, E>
+ : subject_impl<const util::map<K,V>, E>
+ {
+ typedef typename util::map<K,V>::mutable_result mutable_result;
+
+ mutable_result operator()(const K& key);
+ mutable_result operator[](const K& key);
+
+ void clear();
+
+ std::map<K,V,util::ord<K> > hook_std_map_();
+
+ private:
+ E& exact_();
+ };
+
+
+ } // end of namespace mln::internal
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace util
+ {
+
+ // util::map<K,V>
+
+
+ template <typename K, typename V>
+ inline
+ map<K,V>::map()
+ {
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map<K,V>::clear()
+ {
+ m_.clear();
+ mln_postcondition(is_empty());
+ }
+
+ template <typename K, typename V>
+ inline
+ unsigned
+ map<K,V>::size() const
+ {
+ return nelements();
+ }
+
+ template <typename K, typename V>
+ inline
+ unsigned
+ map<K,V>::nelements() const
+ {
+ return m_.size();
+ }
+
+ template <typename K, typename V>
+ inline
+ typename map<K,V>::ro_result
+ map<K,V>::operator()(const K& key) const
+ {
+// mln_precondition(has(key));
+ return (*this)[key];
+ }
+
+ template <typename K, typename V>
+ inline
+ typename map<K,V>::mutable_result
+ map<K,V>::operator()(const K& key)
+ {
+// mln_precondition(has(key));
+ return (*this)[key];
+ }
+
+ template <typename K, typename V>
+ inline
+ typename map<K,V>::ro_result
+ map<K,V>::operator[](const K& key) const
+ {
+// mln_precondition(has(key));
+ return m_[key];
+ }
+
+ template <typename K, typename V>
+ inline
+ typename map<K,V>::mutable_result
+ map<K,V>::operator[](const K& key)
+ {
+// mln_precondition(has(key));
+ return m_[key];
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map<K,V>::erase(const K& key)
+ {
+ mln_precondition(has(key));
+ m_.erase(key);
+ }
+
+ template <typename K, typename V>
+ inline
+ bool
+ map<K,V>::has(const K& key) const
+ {
+ return m_.find(key) != m_.end();
+ }
+
+ template <typename K, typename V>
+ inline
+ bool
+ map<K,V>::is_empty() const
+ {
+ return nelements() == 0;
+ }
+
+ template <typename K, typename V>
+ inline
+ const std::map<K,V,util::ord<K> >&
+ map<K,V>::std_map() const
+ {
+ return m_;
+ }
+
+ template <typename K, typename V>
+ inline
+ std::map<K,V,util::ord<K> >&
+ map<K,V>::hook_std_map_()
+ {
+ return m_;
+ }
+
+
+ // util::map_fwd_iter<K,V>
+
+
+ template <typename K, typename V>
+ inline
+ map_fwd_iter<K,V>::map_fwd_iter()
+ {
+ a_ = 0;
+ }
+
+ template <typename K, typename V>
+ inline
+ map_fwd_iter<K,V>::map_fwd_iter(const map<K,V>& a)
+ {
+ change_target(a);
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_fwd_iter<K,V>::change_target(const map<K,V>& a)
+ {
+ a_ = &a.std_map();
+ invalidate();
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_fwd_iter<K,V>::start()
+ {
+ mln_precondition(a_ != 0);
+ i_ = a_->begin();
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_fwd_iter<K,V>::next()
+ {
+ mln_precondition(is_valid());
+ ++i_;
+ }
+
+ template <typename K, typename V>
+ inline
+ bool
+ map_fwd_iter<K,V>::is_valid() const
+ {
+ return i_ != a_->end();
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_fwd_iter<K,V>::invalidate()
+ {
+ if (a_ != 0)
+ i_ = a_->end();
+ mln_postcondition(! is_valid());
+ }
+
+ template <typename K, typename V>
+ inline
+ const std::pair<K,V>&
+ map_fwd_iter<K,V>::element() const
+ {
+ mln_precondition(is_valid());
+ return *i_;
+ }
+
+ template <typename K, typename V>
+ inline
+ typename map_fwd_iter<K,V>::subj_t
+ map_fwd_iter<K,V>::subj_()
+ {
+ mln_precondition(is_valid());
+ return *i_;
+ }
+
+
+
+ // util::map_bkd_iter<K,V>
+
+
+ template <typename K, typename V>
+ inline
+ map_bkd_iter<K,V>::map_bkd_iter()
+ {
+ a_ = 0;
+ }
+
+ template <typename K, typename V>
+ inline
+ map_bkd_iter<K,V>::map_bkd_iter(const map<K,V>& a)
+ {
+ change_target(a);
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_bkd_iter<K,V>::change_target(const map<K,V>& a)
+ {
+ a_ = &a.std_map();
+ invalidate();
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_bkd_iter<K,V>::start()
+ {
+ mln_precondition(a_ != 0);
+ if (! a_->empty())
+ i_ = a_->rbegin();
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_bkd_iter<K,V>::next()
+ {
+ mln_precondition(is_valid());
+ ++i_;
+ }
+
+ template <typename K, typename V>
+ inline
+ bool
+ map_bkd_iter<K,V>::is_valid() const
+ {
+ return i_ != a_->rend();
+ }
+
+ template <typename K, typename V>
+ inline
+ void
+ map_bkd_iter<K,V>::invalidate()
+ {
+ if (a_ != 0)
+ i_ = a_->rend();
+ mln_postcondition(! is_valid());
+ }
+
+ template <typename K, typename V>
+ inline
+ const std::pair<K,V>&
+ map_bkd_iter<K,V>::element() const
+ {
+ mln_precondition(is_valid());
+ return *i_;
+ }
+
+ template <typename K, typename V>
+ inline
+ typename map_bkd_iter<K,V>::subj_t
+ map_bkd_iter<K,V>::subj_()
+ {
+ mln_precondition(is_valid());
+ return *i_;
+ }
+
+
+ // Operator <<.
+
+ template <typename K, typename V>
+ std::ostream& operator<<(std::ostream& ostr,
+ const map<K,V>& a)
+ {
+ ostr << '{';
+ typedef map<K,V> M;
+ mln_eiter(M) e(a);
+ unsigned i = 0;
+ for_all(e)
+ {
+ ostr << "(" << e.first << "," << e.second << ")";
+ if (i != e.nelements())
+ ostr << ", ";
+ ++i;
+ }
+ ostr << '}';
+ return ostr;
+ }
+
+
+ // Operator <<.
+
+ template <typename K, typename V>
+ bool operator==(const map<K,V>& lhs,
+ const map<K,V>& rhs)
+ {
+ return lhs.std_map() == rhs.std_map();
+ }
+
+ } // end of namespace mln::util
+
+
+ namespace internal
+ {
+
+ template <typename K, typename V, typename E>
+ inline
+ typename subject_impl<util::map<K,V>, E>::mutable_result
+ subject_impl<util::map<K,V>, E>::operator()(const K& key)
+ {
+ return exact_().get_subject()(key);
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ typename subject_impl<util::map<K,V>, E>::mutable_result
+ subject_impl<util::map<K,V>, E>::operator[](const K& key)
+ {
+ return exact_().get_subject()[key];
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ void
+ subject_impl<util::map<K,V>, E>::clear()
+ {
+ exact_().get_subject().clear();
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ std::map<K,V,util::ord<K> >
+ subject_impl<util::map<K,V>, E>::hook_std_map_()
+ {
+ return exact_().get_subject().hook_std_map_();
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ E&
+ subject_impl<util::map<K,V>, E >::exact_()
+ {
+ return internal::force_exact<E>(*this);
+ }
+
+
+ template <typename K, typename V, typename E>
+ inline
+ unsigned
+ subject_impl<const util::map<K,V>, E>::size() const
+ {
+ return exact_().get_subject().size();
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ unsigned
+ subject_impl<const util::map<K,V>, E>::nelements() const
+ {
+ return exact_().get_subject().nelements();
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ bool
+ subject_impl<const util::map<K,V>, E>::is_empty() const
+ {
+ return exact_().get_subject().is_empty();
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ typename subject_impl<const util::map<K,V>, E>::ro_result
+ subject_impl<const util::map<K,V>, E>::operator()(const K& key) const
+ {
+ return exact_().get_subject()(key);
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ typename subject_impl<const util::map<K,V>, E>::ro_result
+ subject_impl<const util::map<K,V>, E>::operator[](const K& key) const
+ {
+ return exact_().get_subject()[key];
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ const std::map<K,V,util::ord<K> >
+ subject_impl<const util::map<K,V>, E>::std_map() const
+ {
+ return exact_().get_subject().std_map();
+ }
+
+ template <typename K, typename V, typename E>
+ inline
+ const E&
+ subject_impl<const util::map<K,V>, E >::exact_() const
+ {
+ return internal::force_exact<const E>(*this);
+ }
+
+
+ } // end of namespace mln::internal
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+} // end of namespace mln
+
+#endif // ! MLN_UTIL_MAP_HH
diff --git a/milena/tests/util/Makefile.am b/milena/tests/util/Makefile.am
index f60b0d8..4e68e04 100644
--- a/milena/tests/util/Makefile.am
+++ b/milena/tests/util/Makefile.am
@@ -28,6 +28,7 @@ check_PROGRAMS = \
lazy_set \
lemmings \
line_graph \
+ map \
ord \
ord_pair \
set \
@@ -45,6 +46,7 @@ graph_SOURCES = graph.cc
lazy_set_SOURCES = lazy_set.cc
lemmings_SOURCES = lemmings.cc
line_graph_SOURCES = line_graph.cc
+map_SOURCES = map.cc
ord_SOURCES = ord.cc
ord_pair_SOURCES = ord_pair.cc
set_SOURCES = set.cc
diff --git a/milena/tests/data/compute_in_inner_border.cc b/milena/tests/util/map.cc
similarity index 63%
copy from milena/tests/data/compute_in_inner_border.cc
copy to milena/tests/util/map.cc
index da73bd2..7d38249 100644
--- a/milena/tests/data/compute_in_inner_border.cc
+++ b/milena/tests/util/map.cc
@@ -23,29 +23,46 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#include <mln/core/image/image2d.hh>
-#include <mln/data/compute_in_inner_border.hh>
-#include <mln/debug/iota.hh>
-#include <mln/accu/stat/mean.hh>
+#include <mln/util/map.hh>
-int main()
+const char *keys[] = { 0, "1", "2", "3", "4" };
+
+int main ()
{
using namespace mln;
+ typedef util::map<std::string, unsigned> map_t;
+ map_t m;
+
+ m["1"] = 1;
+ m["2"] = 2;
+ m["3"] = 3;
+ m["4"] = 4;
+
+ mln_assertion(m.nelements() == 4);
- image2d<int> ima(10, 10);
- debug::iota(ima);
+ mln_assertion(m.has("3"));
+ m.erase("3");
+ mln_assertion(!m.has("3"));
+ m.clear();
+ mln_assertion(m.is_empty());
{
- accu::stat::mean<int> m;
- float mean = data::compute_in_inner_border(m, ima, 1);
- mln_assertion(mean == 50.5);
+ unsigned i = 1;
+ mln_eiter(map_t) e(m);
+ for_all(e)
+ {
+ mln_assertion(keys[i] == e.get_subject().first);
+ mln_assertion(i++ == e.get_subject().second);
+ }
}
{
- accu::stat::mean<int> m;
- float mean = data::compute_in_inner_border(m, ima, 2);
- mln_assertion(mean == 50.5);
+ unsigned i = 4;
+ mln_bkd_eiter(map_t) e(m);
+ for_all(e)
+ {
+ mln_assertion(keys[i] == e.get_subject().first);
+ mln_assertion(i-- == e.get_subject().second);
+ }
}
-
-
}
--
1.7.2.5
1
0
---
milena/ChangeLog | 4 +++
milena/mln/inner_border/{extend.hh => remove.hh} | 30 +++++++++++-----------
2 files changed, 19 insertions(+), 15 deletions(-)
copy milena/mln/inner_border/{extend.hh => remove.hh} (73%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 7a45b8b..473f717 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,9 @@
2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * mln/inner_border/remove.hh: New.
+
+2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Add new v2v functions.
* mln/fun/v2v/ceil.hh,
diff --git a/milena/mln/inner_border/extend.hh b/milena/mln/inner_border/remove.hh
similarity index 73%
copy from milena/mln/inner_border/extend.hh
copy to milena/mln/inner_border/remove.hh
index 08c1901..bb9393d 100644
--- a/milena/mln/inner_border/extend.hh
+++ b/milena/mln/inner_border/remove.hh
@@ -23,15 +23,15 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_INNER_BORDER_EXTEND_HH
-# define MLN_INNER_BORDER_EXTEND_HH
+#ifndef MLN_INNER_BORDER_REMOVE_HH
+# define MLN_INNER_BORDER_REMOVE_HH
/// \file
///
-/// \brief Extend the inner border of an image.
+/// \brief Remove the inner border of an image.
# include <mln/core/image/image2d.hh>
-# include <mln/data/paste.hh>
+# include <mln/data/paste_without_localization.hh>
namespace mln
@@ -40,42 +40,42 @@ namespace mln
namespace inner_border
{
- /// \brief Extend the inner border of an image.
+ /// \brief Remove the inner border of an image.
template <typename I>
mln_concrete(I)
- extend(const Image<I>& input, unsigned inner_border_size);
+ remove(const Image<I>& input, unsigned inner_border_size);
/// \overload
/// inner_border_size is set to 1.
template <typename I>
mln_concrete(I)
- extend(const Image<I>& input);
+ remove(const Image<I>& input);
# ifndef MLN_INCLUDE_ONLY
template <typename I>
mln_concrete(I)
- extend(const Image<I>& input_, unsigned inner_border_size)
+ remove(const Image<I>& input_, unsigned inner_border_size)
{
- trace::entering("mln::inner_border::extend");
+ trace::entering("mln::inner_border::remove");
mln_precondition(exact(input_).is_valid());
const I& input = exact(input_);
box2d b = input.domain(), bb = b;
- bb.enlarge(inner_border_size);
+ bb.enlarge(- inner_border_size);
mln_concrete(I) output(bb);
- data::paste(input, output);
+ data::paste_without_localization(input | bb, output);
- trace::exiting("mln::inner_border::extend");
+ trace::exiting("mln::inner_border::remove");
return output;
}
template <typename I>
mln_concrete(I)
- extend(const Image<I>& input)
+ remove(const Image<I>& input)
{
- return extend(input, 1);
+ return remove(input, 1);
}
# endif // ! MLN_INCLUDE_ONLY
@@ -84,4 +84,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_INNER_BORDER_EXTEND_HH
+#endif // ! MLN_INNER_BORDER_REMOVE_HH
--
1.7.2.5
1
0
* mln/fun/v2v/ceil.hh,
* mln/fun/v2v/floor.hh: New.
---
milena/ChangeLog | 7 ++++++
milena/mln/fun/v2v/{abs.hh => ceil.hh} | 36 ++++++++++++++++++-------------
milena/mln/fun/v2v/{abs.hh => floor.hh} | 35 ++++++++++++++++++------------
3 files changed, 49 insertions(+), 29 deletions(-)
copy milena/mln/fun/v2v/{abs.hh => ceil.hh} (76%)
copy milena/mln/fun/v2v/{abs.hh => floor.hh} (75%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index d3e2f30..7a45b8b 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,12 @@
2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add new v2v functions.
+
+ * mln/fun/v2v/ceil.hh,
+ * mln/fun/v2v/floor.hh: New.
+
+2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Small fixes.
* mln/border/get.hh: Add a new implementation for handling morphed
diff --git a/milena/mln/fun/v2v/abs.hh b/milena/mln/fun/v2v/ceil.hh
similarity index 76%
copy from milena/mln/fun/v2v/abs.hh
copy to milena/mln/fun/v2v/ceil.hh
index c2b34b3..3d54a10 100644
--- a/milena/mln/fun/v2v/abs.hh
+++ b/milena/mln/fun/v2v/ceil.hh
@@ -1,5 +1,4 @@
-// Copyright (C) 2007, 2009, 2012 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -24,17 +23,16 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_FUN_V2V_ABS_HH
-# define MLN_FUN_V2V_ABS_HH
+#ifndef MLN_FUN_V2V_CEIL_HH
+# define MLN_FUN_V2V_CEIL_HH
/*! \file
*
- * \brief FIXME.
+ * \brief Round up input value.
*/
# include <mln/core/concept/function.hh>
-# include <mln/math/abs.hh>
-
+# include <cmath>
namespace mln
{
@@ -45,15 +43,17 @@ namespace mln
namespace v2v
{
- // FIXME: Doc!
- template <typename V, typename R>
- struct abs : public Function_v2v< abs<V,R> >,
- private mlc_converts_to(R,V)::check_t
+ /// \brief Round up input value.
+ template <typename V, typename R = V>
+ struct ceil : public Function_v2v< ceil<V,R> >
{
+ ceil();
+
typedef R result;
typedef V argument;
- R operator()(const V& v) const;
+
+ R operator()(const V& w) const;
};
@@ -61,10 +61,16 @@ namespace mln
template <typename V, typename R>
inline
+ ceil<V,R>::ceil()
+ {
+ }
+
+ template <typename V, typename R>
+ inline
R
- abs<V,R>::operator()(const V& v) const
+ ceil<V,R>::operator()(const V& v) const
{
- return R(mln::math::abs(v));
+ return std::ceil(v);
}
# endif // ! MLN_INCLUDE_ONLY
@@ -76,4 +82,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_FUN_V2V_ABS_HH
+#endif // ! MLN_FUN_V2V_CEIL_HH
diff --git a/milena/mln/fun/v2v/abs.hh b/milena/mln/fun/v2v/floor.hh
similarity index 75%
copy from milena/mln/fun/v2v/abs.hh
copy to milena/mln/fun/v2v/floor.hh
index c2b34b3..1bbdd5a 100644
--- a/milena/mln/fun/v2v/abs.hh
+++ b/milena/mln/fun/v2v/floor.hh
@@ -1,5 +1,4 @@
-// Copyright (C) 2007, 2009, 2012 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2012 EPITA Research and Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -24,16 +23,16 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_FUN_V2V_ABS_HH
-# define MLN_FUN_V2V_ABS_HH
+#ifndef MLN_FUN_V2V_FLOOR_HH
+# define MLN_FUN_V2V_FLOOR_HH
/*! \file
*
- * \brief FIXME.
+ * \brief Round down input value.
*/
# include <mln/core/concept/function.hh>
-# include <mln/math/abs.hh>
+# include <cmath>
namespace mln
@@ -45,15 +44,17 @@ namespace mln
namespace v2v
{
- // FIXME: Doc!
- template <typename V, typename R>
- struct abs : public Function_v2v< abs<V,R> >,
- private mlc_converts_to(R,V)::check_t
+ /// \brief Round down input value.
+ template <typename V, typename R = V>
+ struct floor : public Function_v2v< floor<V,R> >
{
+ floor();
+
typedef R result;
typedef V argument;
- R operator()(const V& v) const;
+
+ R operator()(const V& w) const;
};
@@ -61,10 +62,16 @@ namespace mln
template <typename V, typename R>
inline
+ floor<V,R>::floor()
+ {
+ }
+
+ template <typename V, typename R>
+ inline
R
- abs<V,R>::operator()(const V& v) const
+ floor<V,R>::operator()(const V& v) const
{
- return R(mln::math::abs(v));
+ return std::floor(v);
}
# endif // ! MLN_INCLUDE_ONLY
@@ -76,4 +83,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_FUN_V2V_ABS_HH
+#endif // ! MLN_FUN_V2V_FLOOR_HH
--
1.7.2.5
1
0
* mln/border/get.hh: Add a new implementation for handling morphed
images.
* mln/data/compute.hh: Initialize correctly the accumulator.
* mln/debug/println_with_border.hh,
* mln/debug/println_with_border.spe.hh: Add support for morphed
images.
* mln/value/intsub.hh,
* mln/world/k2/fill_non_primary_from_primary_2_faces.hh: Cleanup code.
* mln/world/k2/immerse.hh: Cast to image value type.
* mln/world/k2/is_non_primary_2_face_center.hh: Fix invalid test.
* mln/world/kn/border/adjust_duplicate_2_faces.hh: Fix doc.
* mln/world/kn/border/fill_1_from_aux_2_faces.hh: Add missing
safe_cast.
* mln/world/kn/compute_tree_of_shapes.hh: Disable debug.
* mln/world/kn/fill_0_from_1_faces.hh,
* mln/world/kn/is_0_or_1_face.hh: Fix ambiguous namespace.
* mln/world/kn/safe_cast.hh: Add a new specialization and fix
another one.
* tests/value/intsub.cc,
* tests/world/k2/un_immerse.cc: Add more tests.
---
milena/ChangeLog | 36 ++++++
milena/mln/border/get.hh | 7 +
milena/mln/data/compute.hh | 5 +-
milena/mln/debug/println_with_border.hh | 30 ++++-
milena/mln/debug/println_with_border.spe.hh | 44 ++++++--
milena/mln/value/intsub.hh | 4 +-
.../k2/fill_non_primary_from_primary_2_faces.hh | 2 -
milena/mln/world/k2/immerse.hh | 12 +-
.../mln/world/k2/is_non_primary_2_face_center.hh | 5 +-
.../world/kn/border/adjust_duplicate_2_faces.hh | 2 +-
.../mln/world/kn/border/fill_1_from_aux_2_faces.hh | 17 ++--
milena/mln/world/kn/compute_tree_of_shapes.hh | 9 +-
milena/mln/world/kn/fill_0_from_1_faces.hh | 4 +-
milena/mln/world/kn/is_0_or_1_face.hh | 2 +-
milena/mln/world/kn/safe_cast.hh | 19 ++-
milena/tests/value/intsub.cc | 9 ++
milena/tests/world/k2/un_immerse.cc | 126 +++++++++++++++++---
17 files changed, 268 insertions(+), 65 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 078df3a..d3e2f30 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,41 @@
2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Small fixes.
+
+ * mln/border/get.hh: Add a new implementation for handling morphed
+ images.
+
+ * mln/data/compute.hh: Initialize correctly the accumulator.
+
+ * mln/debug/println_with_border.hh,
+ * mln/debug/println_with_border.spe.hh: Add support for morphed
+ images.
+
+ * mln/value/intsub.hh,
+ * mln/world/k2/fill_non_primary_from_primary_2_faces.hh: Cleanup code.
+
+ * mln/world/k2/immerse.hh: Cast to image value type.
+
+ * mln/world/k2/is_non_primary_2_face_center.hh: Fix invalid test.
+
+ * mln/world/kn/border/adjust_duplicate_2_faces.hh: Fix doc.
+
+ * mln/world/kn/border/fill_1_from_aux_2_faces.hh: Add missing
+ safe_cast.
+
+ * mln/world/kn/compute_tree_of_shapes.hh: Disable debug.
+
+ * mln/world/kn/fill_0_from_1_faces.hh,
+ * mln/world/kn/is_0_or_1_face.hh: Fix ambiguous namespace.
+
+ * mln/world/kn/safe_cast.hh: Add a new specialization and fix
+ another one.
+
+ * tests/value/intsub.cc,
+ * tests/world/k2/un_immerse.cc: Add more tests.
+
+2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Make use of data::transform in arith::revert.
* mln/arith/revert.hh: Here.
diff --git a/milena/mln/border/get.hh b/milena/mln/border/get.hh
index 3ff713a..8311bc1 100644
--- a/milena/mln/border/get.hh
+++ b/milena/mln/border/get.hh
@@ -71,6 +71,13 @@ namespace mln
return border::get(*ima.delegatee_());
}
+ template <typename I>
+ inline
+ unsigned get_(trait::image::ext_domain::none, trait::image::category::morpher,
+ const I& ima)
+ {
+ return border::get(*ima.delegatee_());
+ }
template <typename I>
inline
diff --git a/milena/mln/data/compute.hh b/milena/mln/data/compute.hh
index 0ab146e..ea6f0b8 100644
--- a/milena/mln/data/compute.hh
+++ b/milena/mln/data/compute.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Copyright (C) 2007, 2008, 2009, 2012 EPITA Research and Development
// Laboratory (LRDE)
//
// This file is part of Olena.
@@ -92,8 +92,7 @@ namespace mln
mln_result(A)
compute(const Accumulator<A>& a_, const Image<I>& input)
{
- (void) a_;
- A a;
+ A a(exact(a_));
return compute(a, input);
}
diff --git a/milena/mln/debug/println_with_border.hh b/milena/mln/debug/println_with_border.hh
index 0099e57..ee6fe16 100644
--- a/milena/mln/debug/println_with_border.hh
+++ b/milena/mln/debug/println_with_border.hh
@@ -48,7 +48,14 @@ namespace mln
namespace debug
{
- /// Print the image \p input on the standard output.
+ /// Print the image \p input on the standard output and display
+ /// text \p msg.
+ template <typename I>
+ inline
+ void
+ println_with_border(const std::string& msg, const Image<I>& input);
+
+ /// \overload
template <typename I>
void println_with_border(const Image<I>& input);
@@ -73,16 +80,31 @@ namespace mln
// Facade.
+
template <typename I>
inline
void
- println_with_border(const Image<I>& input)
+ println_with_border(const Image<I>& input_)
{
- mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
+ const I& input = exact(input_);
+ //mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
+ mln_precondition(input.is_valid());
+ impl::println_with_border(geom::bbox(input), input);
+ }
- impl::println_with_border(geom::bbox(exact(input)), exact(input));
+ template <typename I>
+ inline
+ void
+ println_with_border(const std::string& msg, const Image<I>& input)
+ {
+ if (!quiet)
+ {
+ std::cout << msg << std::endl;
+ println_with_border(input);
+ }
}
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::debug
diff --git a/milena/mln/debug/println_with_border.spe.hh b/milena/mln/debug/println_with_border.spe.hh
index f59f45b..722baad 100644
--- a/milena/mln/debug/println_with_border.spe.hh
+++ b/milena/mln/debug/println_with_border.spe.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008, 2009, 2011 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2011, 2012 EPITA Research and
+// Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -39,6 +39,7 @@
# include <mln/core/concept/window.hh>
# include <mln/debug/format.hh>
# include <mln/opt/element.hh>
+# include <mln/border/get.hh>
namespace mln
{
@@ -59,13 +60,40 @@ namespace mln
void
println_with_border(const box2d& b, const I& input)
{
- const unsigned ncols = b.ncols() + 2 * input.border();
- for (size_t i = 0; i < opt::nelements(input); i++)
- {
- std::cout << format(input.buffer()[i]) << ' ';
- if (((i + 1) % ncols) == 0)
+ accu::stat::max<unsigned> len_;
+ box2d b_ext = b;
+ b_ext.enlarge(border::get(input));
+
+ mln_piter(box2d) p(b_ext);
+ for_all(p)
+ if (input.domain().has(p) || ! b.has(p))
+ {
+ std::ostringstream o;
+ o << format(input(p));
+ len_.take(o.str().length());
+ }
+ unsigned len = len_ + 1;
+
+ image2d<char> output(b_ext.nrows(), b_ext.ncols() * len, 0);
+ data::fill(output, ' ');
+ for_all(p)
+ if (input.domain().has(p) || ! b.has(p))
+ {
+ std::ostringstream oss;
+ oss << format(input(p));
+ def::coord
+ row = static_cast<def::coord>(p.row() - b_ext.min_row()),
+ col = static_cast<def::coord>((p.col() - b_ext.min_col()) * len);
+ point2d w(row, col);
+ put_word(output, w, oss.str());
+ }
+
+ for (def::coord row = 0; row < def::coord(b_ext.nrows()); ++row)
+ {
+ for (def::coord col = 0; col < def::coord(b_ext.ncols() * len); ++col)
+ std::cout << opt::at(output, row, col);
std::cout << std::endl;
- }
+ }
std::cout << std::endl;
}
# endif // MLN_CORE_ALIAS_BOX2D_HH
diff --git a/milena/mln/value/intsub.hh b/milena/mln/value/intsub.hh
index 721b4bd..2b40f89 100644
--- a/milena/mln/value/intsub.hh
+++ b/milena/mln/value/intsub.hh
@@ -311,6 +311,8 @@ namespace mln
intsub<n>::intsub(const intsub<m>& rhs)
{
mln_precondition(m < n);
+ if (m < n)
+ abort();
this->v_ = rhs.to_enc() * (n / m);
}
@@ -516,7 +518,7 @@ namespace mln
mln_trait_routine_mean(2,intsub<n>)
mean_(const intsub<n>& v1, const intsub<n>& v2)
{
- return intsub<2*n>::make_from_enc_((v1.to_enc() + v2.to_enc()));
+ return intsub<2*n>::make_from_enc_(v1.to_enc() + v2.to_enc());
}
template <unsigned n>
diff --git a/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh b/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
index 37b76a5..f8000ad 100644
--- a/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
+++ b/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
@@ -137,13 +137,11 @@ namespace mln
kn::safe_cast(ima(p + 2 * down))));
}
else if (is_non_primary_2_face_center(p))
- {
ima(p) = kn::safe_cast_to<V>(
f_center(kn::safe_cast(ima(p + 2 * up_left)),
kn::safe_cast(ima(p + 2 * up_right)),
kn::safe_cast(ima(p + 2 * down_left)),
kn::safe_cast(ima(p + 2 * down_right))));
- }
// Initialize border.
kn::border::adjust_duplicate_2_faces(ima, 1);
diff --git a/milena/mln/world/k2/immerse.hh b/milena/mln/world/k2/immerse.hh
index af3c18d..7ef9b3c 100644
--- a/milena/mln/world/k2/immerse.hh
+++ b/milena/mln/world/k2/immerse.hh
@@ -32,6 +32,7 @@
# include <mln/core/concept/image.hh>
# include <mln/world/kn/immerse.hh>
+# include <mln/metal/converts_to.hh>
namespace mln
{
@@ -76,10 +77,10 @@ namespace mln
/// \overload
/// 0, 1 and non-primary 2-faces values are set to \p
/// default_value.
- template <typename I, typename V>
+ template <typename I, typename V, typename U>
mln_ch_value(I, V)
immerse(const Image<I>& ima, const V& new_value_type,
- const V& default_value);
+ const U& default_value);
# ifndef MLN_INCLUDE_ONLY
@@ -114,16 +115,17 @@ namespace mln
}
- template <typename I, typename V>
+ template <typename I, typename V, typename U>
mln_ch_value(I,V)
immerse(const Image<I>& ima, const V& new_value_type,
- const V& default_value)
+ const U& default_value)
{
trace::entering("mln::world::k2::immerse");
mln_precondition(exact(ima).is_valid());
+ mlc_converts_to(U,V)::check();
mln_ch_value(I,V)
- output = kn::immerse(ima, 2, new_value_type, default_value);
+ output = kn::immerse(ima, 2, new_value_type, V(default_value));
trace::exiting("mln::world::k2::immerse");
return output;
diff --git a/milena/mln/world/k2/is_non_primary_2_face_center.hh b/milena/mln/world/k2/is_non_primary_2_face_center.hh
index 79d5d37..3bc2467 100644
--- a/milena/mln/world/k2/is_non_primary_2_face_center.hh
+++ b/milena/mln/world/k2/is_non_primary_2_face_center.hh
@@ -31,6 +31,7 @@
# define MLN_WORLD_K2_IS_NON_PRIMARY_2_FACE_CENTER_HH
# include <mln/core/alias/point2d.hh>
+# include <mln/math/abs.hh>
namespace mln
@@ -71,9 +72,9 @@ namespace mln
inline
bool is_non_primary_2_face_center(const mln::def::coord& row,
- const mln::def::coord& col)
+ const mln::def::coord& col)
{
- return (row % 4 == 2) && (col % 4 == 2);
+ return (math::abs(col) % 4 == 2) && (math::abs(row) % 4 == 2);
}
diff --git a/milena/mln/world/kn/border/adjust_duplicate_2_faces.hh b/milena/mln/world/kn/border/adjust_duplicate_2_faces.hh
index bb7f43c..9a0843d 100644
--- a/milena/mln/world/kn/border/adjust_duplicate_2_faces.hh
+++ b/milena/mln/world/kn/border/adjust_duplicate_2_faces.hh
@@ -50,7 +50,7 @@ namespace mln
/*! \brief Adjust border size and duplicate 2 faces in Kn 2D
* images borders.
- \param[in,out] inout A 2D image immersed in KN.
+ \param[in,out] inout A 2D image immersed in Kn.
\param[in] min_thickness The minimum border thickness of \p
inout.
diff --git a/milena/mln/world/kn/border/fill_1_from_aux_2_faces.hh b/milena/mln/world/kn/border/fill_1_from_aux_2_faces.hh
index 629a11d..2377298 100644
--- a/milena/mln/world/kn/border/fill_1_from_aux_2_faces.hh
+++ b/milena/mln/world/kn/border/fill_1_from_aux_2_faces.hh
@@ -85,6 +85,7 @@ namespace mln
I& inout = const_cast<I&>(exact(inout_));
J& aux = const_cast<J&>(exact(aux_));
const F& f = exact(f_);
+ typedef mln_value(I) V;
def::coord
min_row_1 = geom::min_row(inout) - 1,
@@ -97,11 +98,11 @@ namespace mln
if (is_1_face_vertical(min_row_1, col))
{
// First row
- inout.at_(min_row_1, col) = f(aux.at_(min_row_1, col - 1),
- aux.at_(min_row_1, col + 1));
+ inout.at_(min_row_1, col) = safe_cast_to<V>(f(safe_cast(aux.at_(min_row_1, col - 1)),
+ safe_cast(aux.at_(min_row_1, col + 1))));
// Last row
- inout.at_(max_row_1, col) = f(aux.at_(max_row_1, col - 1),
- aux.at_(max_row_1, col + 1));
+ inout.at_(max_row_1, col) = safe_cast_to<V>(f(safe_cast(aux.at_(max_row_1, col - 1)),
+ safe_cast(aux.at_(max_row_1, col + 1))));
}
// Fill vertical border
@@ -109,11 +110,11 @@ namespace mln
if (is_1_face_horizontal(row, min_col_1))
{
// First col
- inout.at_(row, min_col_1) = f(aux.at_(row - 1, min_col_1),
- aux.at_(row + 1, min_col_1));
+ inout.at_(row, min_col_1) = safe_cast_to<V>(f(safe_cast(aux.at_(row - 1, min_col_1)),
+ safe_cast(aux.at_(row + 1, min_col_1))));
// Last col
- inout.at_(row, max_col_1) = f(aux.at_(row - 1, max_col_1),
- aux.at_(row + 1, max_col_1));
+ inout.at_(row, max_col_1) = safe_cast_to<V>(f(safe_cast(aux.at_(row - 1, max_col_1)),
+ safe_cast(aux.at_(row + 1, max_col_1))));
}
trace::exiting("mln::world::kn::fill_1_from_aux_2_faces");
diff --git a/milena/mln/world/kn/compute_tree_of_shapes.hh b/milena/mln/world/kn/compute_tree_of_shapes.hh
index 4a3b226..c29be4d 100644
--- a/milena/mln/world/kn/compute_tree_of_shapes.hh
+++ b/milena/mln/world/kn/compute_tree_of_shapes.hh
@@ -44,6 +44,7 @@
# include <mln/world/kn/hqueue.hh>
# include <mln/util/tree_of_shapes.hh>
# include <mln/world/kn/is_2_face.hh>
+# include <mln/world/kn/safe_cast.hh>
# include <mln/world/k2/is_primary_2_face.hh>
@@ -219,8 +220,8 @@ namespace mln
if (t.level_changes_at(i))
{
- std::cout << "union-find: done with level " << t.level(p) << std::endl;
- kn::debug::println(done);
+ //std::cout << "union-find: done with level " << t.level(p) << std::endl;
+ //kn::debug::println(done);
}
}
@@ -402,8 +403,8 @@ namespace mln
if (q.is_empty_at(lcur))
{
- std::cout << "sort: done with level " << lcur << std::endl;
- kn::debug::println(done);
+ //std::cout << "sort: done with level " << lcur << std::endl;
+ //kn::debug::println(done);
}
}
while (i != N);
diff --git a/milena/mln/world/kn/fill_0_from_1_faces.hh b/milena/mln/world/kn/fill_0_from_1_faces.hh
index 999ddaf..8452136 100644
--- a/milena/mln/world/kn/fill_0_from_1_faces.hh
+++ b/milena/mln/world/kn/fill_0_from_1_faces.hh
@@ -94,7 +94,7 @@ namespace mln
typedef mln_argument(A) arg;
mln_piter(I) p(inout.domain());
for_all(p)
- if (is_0_face(p))
+ if (kn::is_0_face(p))
{
accu.init();
if (inout.domain().has(p + left))
@@ -125,7 +125,7 @@ namespace mln
mln_piter(I) p(inout.domain());
for_all(p)
- if (is_0_face(p))
+ if (kn::is_0_face(p))
inout(p) = safe_cast(f(safe_cast(inout(p + left)),
safe_cast(inout(p + right)),
safe_cast(inout(p + up)),
diff --git a/milena/mln/world/kn/is_0_or_1_face.hh b/milena/mln/world/kn/is_0_or_1_face.hh
index b05f279..8f14c2b 100644
--- a/milena/mln/world/kn/is_0_or_1_face.hh
+++ b/milena/mln/world/kn/is_0_or_1_face.hh
@@ -55,7 +55,7 @@ namespace mln
inline
bool is_0_or_1_face(const point2d& p)
{
- unsigned dim = face_dim(p);
+ unsigned dim = kn::face_dim(p);
return dim == 0 || dim == 1;
}
diff --git a/milena/mln/world/kn/safe_cast.hh b/milena/mln/world/kn/safe_cast.hh
index 9d5202d..39fc7d7 100644
--- a/milena/mln/world/kn/safe_cast.hh
+++ b/milena/mln/world/kn/safe_cast.hh
@@ -256,18 +256,21 @@ namespace mln
to = from;
}
- // From intsub<n>
+ // From float
template <unsigned n>
- void safe_cast_(const intsub<n>& from, intsub<2*n>& to)
+ void safe_cast_(const float& from, intsub<n>& to)
{
- to = static_cast<intsub<2*n> >(from.to_int());
+ to = from;
}
+
+ // From intsub<n>
+
template <unsigned n>
- void safe_cast_(const intsub<n>& from, intsub<n/2>& to)
+ void safe_cast_(const intsub<n>& from, intsub<2*n>& to)
{
- to = static_cast<intsub<n/2> >(from.to_int());
+ to = static_cast<intsub<2*n> >(from.to_int());
}
template <unsigned n, unsigned m>
@@ -290,6 +293,12 @@ namespace mln
to = from;
}
+ template <unsigned n>
+ void safe_cast_(const intsub<n>& from, float& to)
+ {
+ to = from;
+ }
+
template <unsigned n, unsigned m>
void safe_cast_(const intsub<n>& from, interval<int_u<m> >& to)
{
diff --git a/milena/tests/value/intsub.cc b/milena/tests/value/intsub.cc
index 2ec4671..248af6c 100644
--- a/milena/tests/value/intsub.cc
+++ b/milena/tests/value/intsub.cc
@@ -117,4 +117,13 @@ int main()
// 2.5 * 10.25
mln_assertion((l * k) == 25.625);
+
+ // Mean with 2 intsub
+ mln_assertion(math::mean(intsub<2>(2), intsub<2>(4)) == 3);
+
+ // Mean with 4 intsub
+ mln_assertion(math::mean(intsub<2>(2), intsub<2>(4), intsub<2>(6), intsub<2>(8)) == 5);
+
+ // Add 2 intsub
+ mln_assertion((intsub<2>(2) + intsub<2>(3)) == 5);
}
diff --git a/milena/tests/world/k2/un_immerse.cc b/milena/tests/world/k2/un_immerse.cc
index acb7012..0c4a23d 100644
--- a/milena/tests/world/k2/un_immerse.cc
+++ b/milena/tests/world/k2/un_immerse.cc
@@ -33,23 +33,111 @@ int main()
{
using namespace mln;
- int refvals[2][2] = {
- {1, 2},
- {3, 4}
- };
- image2d<int> ref = make::image(refvals);
-
- int vals[][7] = {
- {0, 0, 0, 0, 0, 0, 0},
- {0, 1, 0, 0, 0, 2, 0},
- {0, 0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0, 0},
- {0, 3, 0, 0, 0, 4, 0},
- {0, 0, 0, 0, 0, 0, 0}
- };
- image2d<int> imak2 = make::image(vals, point2d(-1, -1));
-
- image2d<int> imak0 = world::k2::un_immerse(imak2);
- mln_assertion(imak0 == ref);
+ {
+ int refvals[2][2] = {
+ {1, 2},
+ {4, 5}
+ };
+ image2d<int> ref = make::image(refvals);
+
+ int vals[9][9] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 0, 0, 0, 2, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 4, 0, 0, 0, 5, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0}
+ };
+ image2d<int> imak2 = make::image(vals, point2d(-1, -1));
+
+ image2d<int> imak0 = world::k2::un_immerse(imak2);
+ mln_assertion(imak0 == ref);
+ }
+
+
+ {
+ int refvals[3][3] = {
+ {1, 2, 3},
+ {4, 5, 6},
+ {7, 8, 9}
+ };
+ image2d<int> ref = make::image(refvals);
+
+ int vals[13][13] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 7, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ };
+ image2d<int> imak2 = make::image(vals, point2d(-1, -1));
+
+ image2d<int> imak0 = world::k2::un_immerse(imak2);
+ mln_assertion(imak0 == ref);
+ }
+
+ {
+ int refvals[2][3] = {
+ {1, 2, 3},
+ {4, 5, 6}
+ };
+ image2d<int> ref = make::image(refvals);
+
+ int vals[9][13] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 4, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
+ };
+ image2d<int> imak2 = make::image(vals, point2d(-1, -1));
+
+ image2d<int> imak0 = world::k2::un_immerse(imak2);
+ mln_assertion(imak0 == ref);
+ }
+
+ {
+ int refvals[3][2] = {
+ {1, 2},
+ {4, 5},
+ {7, 8}
+ };
+ image2d<int> ref = make::image(refvals);
+
+ int vals[13][9] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 1, 0, 0, 0, 2, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 4, 0, 0, 0, 5, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 7, 0, 0, 0, 8, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ };
+ image2d<int> imak2 = make::image(vals, point2d(-1, -1));
+
+ image2d<int> imak0 = world::k2::un_immerse(imak2);
+ mln_assertion(imak0 == ref);
+ }
+
}
--
1.7.2.5
1
0

olena-2.0-184-g4fa5991 Make use of data::transform in arith::revert.
by Guillaume Lazzara 04 Jan '13
by Guillaume Lazzara 04 Jan '13
04 Jan '13
* mln/arith/revert.hh: Here.
* mln/arith/revert.spe.hh: Remove.
* mln/fun/v2v/revert.hh: New.
---
milena/ChangeLog | 10 +++
milena/mln/arith/revert.hh | 97 ++---------------------
milena/mln/arith/revert.spe.hh | 84 --------------------
milena/mln/fun/{vv2v/span.hh => v2v/revert.hh} | 32 +++++----
4 files changed, 37 insertions(+), 186 deletions(-)
delete mode 100644 milena/mln/arith/revert.spe.hh
copy milena/mln/fun/{vv2v/span.hh => v2v/revert.hh} (72%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cafb263..078df3a 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,13 @@
+2013-01-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Make use of data::transform in arith::revert.
+
+ * mln/arith/revert.hh: Here.
+
+ * mln/arith/revert.spe.hh: Remove.
+
+ * mln/fun/v2v/revert.hh: New.
+
2012-11-29 Guillaume Lazzara <z(a)lrde.epita.fr>
Remove kn::internal::display.
diff --git a/milena/mln/arith/revert.hh b/milena/mln/arith/revert.hh
index 2ac3710..eefcb83 100644
--- a/milena/mln/arith/revert.hh
+++ b/milena/mln/arith/revert.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008, 2009, 2010 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2010, 2012 EPITA Research and
+// Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -30,19 +30,11 @@
/// \file
///
/// Point-wise revert (min -> max and max -> min) of images.
-///
-/// \todo Add static assertion and save one iterator in in-place version.
# include <mln/core/concept/image.hh>
-# include <mln/trait/value_.hh>
-
-// Specializations are in:
-# include <mln/arith/revert.spe.hh>
-
-
-// FIXME: Rely instead on mln/fun/v2v/revert.hh.
-// FIXME: Revert on int value 0 does not give 0 (since min != - max;
-// idem for float etc.)
+# include <mln/fun/v2v/revert.hh>
+# include <mln/data/transform.hh>
+# include <mln/data/transform_inplace.hh>
namespace mln
@@ -82,77 +74,6 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
- namespace impl
- {
-
- namespace generic
- {
-
- template <typename I, typename O>
- inline
- void revert(const Image<I>& input_, Image<O>& output_)
- {
- trace::entering("arith::impl::generic::revert_");
-
- const I& input = exact(input_);
- O& output = exact(output_);
-
- mln_precondition(input.is_valid());
- mln_precondition(output.is_valid());
- mln_precondition(input.domain() == output.domain());
-
- typedef mln_value(I) V;
- mln_piter(I) p(input.domain());
- for_all(p)
- output(p) = mln_min(V) + (mln_max(V) - input(p));
-
- trace::exiting("arith::impl::generic::revert_");
- }
-
- } // end of namespace mln::arith::impl::generic
-
- } // end of namespace mln::arith::impl
-
-
-
- // Dispatch.
-
- namespace internal
- {
-
- template <typename I, typename O>
- inline
- void
- revert_dispatch(trait::image::speed::any, const I& input, O& output)
- {
- impl::generic::revert(input, output);
- }
-
- template <typename I, typename O>
- inline
- void
- revert_dispatch(trait::image::speed::fastest, const I& input, O& output)
- {
- impl::revert_fastest(input, output);
- }
-
- template <typename I, typename O>
- inline
- void
- revert_dispatch(const Image<I>& input, Image<O>& output)
- {
- revert_dispatch(mln_trait_image_speed(I)(),
- exact(input), exact(output));
-
- }
-
-
- } // end of namespace mln::arith::internal
-
-
-
- // Facades.
-
template <typename I>
inline
mln_concrete(I) revert(const Image<I>& input)
@@ -161,9 +82,8 @@ namespace mln
mln_precondition(exact(input).is_valid());
- mln_concrete(I) output;
- initialize(output, input);
- internal::revert_dispatch(exact(input), exact(output));
+ typedef mln_value(I) V;
+ mln_concrete(I) output = data::transform(input, fun::v2v::revert<V>());
trace::exiting("arith::revert");
return output;
@@ -177,7 +97,8 @@ namespace mln
mln_precondition(exact(input).is_valid());
- internal::revert_dispatch(exact(input), exact(input));
+ typedef mln_value(I) V;
+ data::transform_inplace(input, fun::v2v::revert<V>());
trace::exiting("arith::revert_inplace");
}
diff --git a/milena/mln/arith/revert.spe.hh b/milena/mln/arith/revert.spe.hh
deleted file mode 100644
index 2df8bc0..0000000
--- a/milena/mln/arith/revert.spe.hh
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (C) 2007, 2008, 2009, 2010 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_ARITH_REVERT_SPE_HH
-# define MLN_ARITH_REVERT_SPE_HH
-
-/// \file
-///
-/// Specializations for mln::arith::revert.
-
-# ifndef MLN_ARITH_REVERT_HH
-# error "Forbidden inclusion of *.spe.hh"
-# endif // ! MLN_ARITH_REVERT_HH
-
-# include <mln/core/concept/image.hh>
-# include <mln/trait/value_.hh>
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-namespace mln
-{
-
- namespace arith
- {
-
- namespace impl
- {
-
- // FIXME: This is a fast implementation not a fastest one!
- template <typename I, typename O>
- inline
- void revert_fastest(const Image<I>& input_, Image<O>& output_)
- {
- trace::entering("arith::impl::revert_fastest");
-
- const I& input = exact(input_);
- O& output = exact(output_);
-
- mln_precondition(input.is_valid());
- mln_precondition(output.is_valid());
- mln_precondition(input.domain() == output.domain());
-
- typedef mln_value(I) V;
- mln_pixter(const I) ip(input);
- mln_pixter(O) op(output);
- for_all_2(ip, op)
- op.val() = mln_min(V) + (mln_max(V) - ip.val());
-
- trace::entering("arith::impl::revert_fastest");
- }
-
- } // end of namespace mln::arith::impl
-
- } // end of namespace mln::arith
-
-} // end of namespace mln
-
-# endif // ! MLN_INCLUDE_ONLY
-
-#endif // ! MLN_ARITH_REVERT_SPE_HH
diff --git a/milena/mln/fun/vv2v/span.hh b/milena/mln/fun/v2v/revert.hh
similarity index 72%
copy from milena/mln/fun/vv2v/span.hh
copy to milena/mln/fun/v2v/revert.hh
index 680db34..b62fd26 100644
--- a/milena/mln/fun/vv2v/span.hh
+++ b/milena/mln/fun/v2v/revert.hh
@@ -23,15 +23,18 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-#ifndef MLN_FUN_VV2V_SPAN_HH
-# define MLN_FUN_VV2V_SPAN_HH
+#ifndef MLN_FUN_V2V_REVERT_HH
+# define MLN_FUN_V2V_REVERT_HH
/// \file
///
-/// Functor that computes the spanimum of two values.
+/// Function reverting given values.
-# include <mln/math/span.hh>
-# include <mln/core/concept/function.hh>
+// FIXME: Revert on int value 0 does not give 0 (since min != - max;
+// idem for float etc.)
+
+
+# include <mln/fun/internal/selector.hh>
namespace mln
@@ -40,18 +43,19 @@ namespace mln
namespace fun
{
- namespace vv2v
+ namespace v2v
{
- // FIXME: Doc.
+ // FIXME: Doc!
- /// \brief A functor computing the span of two interval values.
template <typename T, typename R = T>
- struct span : public Function_vv2v< span<T,R> >
+ struct revert
+ : fun::internal::selector_<R, T, revert<T,R> >::ret
{
typedef R result;
+ typedef T argument;
- R operator()(const T& v1, const T& v2) const;
+ R operator()(const T& v) const;
};
@@ -59,18 +63,18 @@ namespace mln
template <typename T, typename R>
R
- span<T,R>::operator()(const T& v1, const T& v2) const
+ revert<T,R>::operator()(const T& v) const
{
- return R(math::span(v1, v2));
+ return static_cast<R>(mln_min(T) + (mln_max(T) - v));
}
# endif // ! MLN_INCLUDE_ONLY
- } // end of namespace mln::fun::vv2v
+ } // end of namespace mln::fun::v2v
} // end of namespace mln::fun
} // end of namespace mln
-#endif // ! MLN_FUN_VV2V_SPAN_HH
+#endif // ! MLN_FUN_V2V_REVERT_HH
--
1.7.2.5
1
0

olena-2.0-134-gb0bb6e9 mln/labeling/colorize.hh: Do not recompute previously computed colors.
by Guillaume Lazzara 03 Jan '13
by Guillaume Lazzara 03 Jan '13
03 Jan '13
---
milena/ChangeLog | 5 +++++
milena/mln/labeling/colorize.hh | 6 +++---
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index d9f0ffa..f970f00 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,8 @@
+2013-01-03 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ * mln/labeling/colorize.hh: Do not recompute previously computed
+ colors.
+
2012-11-13 Guillaume Lazzara <z(a)lrde.epita.fr>
* mln/histo/equalize.hh: Fix.
diff --git a/milena/mln/labeling/colorize.hh b/milena/mln/labeling/colorize.hh
index ddfbb15..730929e 100644
--- a/milena/mln/labeling/colorize.hh
+++ b/milena/mln/labeling/colorize.hh
@@ -1,5 +1,5 @@
-// Copyright (C) 2008, 2009, 2010, 2011 EPITA Research and Development
-// Laboratory (LRDE)
+// Copyright (C) 2008, 2009, 2010, 2011, 2013 EPITA Research and
+// Development Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -204,8 +204,8 @@ namespace mln
if (diff_size < 0)
{
srand(1);
+ unsigned i = f.size();
f.resize(label_count);
- unsigned i = f.size() + diff_size;
// We want to treat comp 0 differently since it is the background.
if (i == 0)
{
--
1.7.2.5
1
0