https://svn.lrde.epita.fr/svn/oln/trunk
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Fix various accumulators things.
Have transform_line fastest.
* milena/mln/accu/transform_line.hh: Add documentation.
(todo): Remove, done:
The specialization for fastest images is now up.
(todo): New. A version that ignores extensions should
exist; see commented code in this present file.
(impl::generic::transform_line): Add extension adjust for
safety reason.
Layout.
(impl::generic::transform_line_fastest): Activate.
Fix bug.
(transform_line_dispatch): Revamp to take into account
accumulator properties.
(transform_line): Call properly the dispatch mechanism.
* milena/tests/accu/transform_line.cc: Test both generic and
fastest versions.
Fix missing properties for some accumulators.
* milena/mln/accu/stat/min.hh,
* milena/mln/accu/stat/max.hh (set_value): New method.
* milena/mln/accu/stat/max_h.hh (invariant_): New method.
(max_h): Add calls to invariant_.
(debug_print_): Augment.
* milena/mln/accu/math/count.hh,
* milena/mln/accu/logic/lor.hh,
* milena/mln/accu/logic/lor_basic.hh,
* milena/mln/accu/logic/land.hh,
* milena/mln/accu/logic/land_basic.hh,
* milena/mln/accu/stat/min.hh,
* milena/mln/accu/stat/max.hh,
* milena/mln/accu/stat/min_h.hh,
* milena/mln/accu/stat/max_h.hh (trait): Add missing traits.
Misc.
* milena/mln/morpho/general.spe.hh: Fix layout.
Remove useless includes.
mln/accu/logic/land.hh | 30 ++++-
mln/accu/logic/land_basic.hh | 29 ++++
mln/accu/logic/lor.hh | 29 ++++
mln/accu/logic/lor_basic.hh | 29 ++++
mln/accu/math/count.hh | 52 ++++----
mln/accu/stat/max.hh | 40 +++++-
mln/accu/stat/max_h.hh | 65 +++++++++-
mln/accu/stat/min.hh | 40 +++++-
mln/accu/stat/min_h.hh | 28 +++-
mln/accu/transform_line.hh | 258 +++++++++++++++++++++++++++++++++++--------
mln/morpho/general.spe.hh | 34 ++---
tests/accu/transform_line.cc | 13 +-
12 files changed, 500 insertions(+), 147 deletions(-)
Index: milena/mln/accu/transform_line.hh
--- milena/mln/accu/transform_line.hh (revision 4351)
+++ milena/mln/accu/transform_line.hh (working copy)
@@ -31,17 +31,20 @@
///
/// Run an accumulator over a line (in a particular direction).
///
+/// This operator takes into account a possible domain extension so
+/// the user has to adjust and set the extension before calling
+/// accu::transform_line.
+///
/// \todo Import code from sandox/geraud/browsing/fwd.cc to handle the
/// case of no-domain-extension.
///
-/// \todo Specialize for fastest images.
+/// \todo Make a particular version that ignores any domain extension.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/meta_accumulator.hh>
# include <mln/extension/adjust.hh>
-
namespace mln
{
@@ -73,7 +76,8 @@
{
template <typename A, typename I>
- void transform_line_tests(const Accumulator<A>& a_, const
Image<I>& input_)
+ void
+ transform_line_tests(const Accumulator<A>& a_, const Image<I>&
input_)
{
A a = exact(a_);
const I& input = exact(input_);
@@ -114,6 +118,8 @@
internal::transform_line_tests(a, input);
+ extension::adjust(input, length / 2); // Safety.
+
mln_ch_value(I, mln_result(A)) output;
initialize(output, input);
@@ -156,23 +162,24 @@
while (p_dir < pmax_dir)
{
- ++p_dir;
if (input.has(qt))
a.take(input(qt));
+ qt_dir++;
+
if (input.has(qu))
a.untake(input(qu));
+ qu_dir++;
+
+ ++p_dir;
if (input.has(p))
output(p) = a.to_result();
- qt_dir++;
- qu_dir++;
}
- p_dir = pmin_dir;
-
-
// Go to the next line.
// --------------------
+ p_dir = pmin_dir;
+
for (int c = P::dim - 1; c >= 0; --c)
{
if (c == int(dir))
@@ -194,7 +201,6 @@
} // end of namespace mln::accu::impl::generic
-
template <typename A, typename I>
inline
mln_ch_value(I, mln_result(A))
@@ -209,69 +215,198 @@
internal::transform_line_tests(a, input);
+ extension::adjust(input, length / 2); // Safety.
+
mln_ch_value(I, mln_result(A)) output;
initialize(output, input);
typedef mln_psite(I) P;
+ const P
+ pmin = input.domain().pmin(),
+ pmax = input.domain().pmax();
+ const def::coord
+ pmax_dir = pmax[dir],
+ pmin_dir = pmin[dir];
+
+ P p = pmin; // Starting point.
+ def::coord& p_dir = p[dir];
+ // Step.
mln_delta(P) dp(literal::zero);
dp[dir] = 1;
int step = input.delta_index(dp);
- P pmin = input.domain().pmin(),
+ do
+ {
+ // Start the line.
+ // ---------------
+
+ unsigned o_p = input.index_of_point(p);
+ unsigned o_qt = o_p - (length / 2) * step;
+ unsigned o_qu = o_qt;
+ a.init();
+
+ for (unsigned i = 0; i < length; ++i)
+ // t o | x o o
+ // ...
+ // o o | x o t
+ {
+ a.take(input.element(o_qt));
+ o_qt += step;
+ }
+ output.element(o_p) = a.to_result();
+
+ // Browse the line.
+ // ----------------
+
+ while (p_dir < pmax_dir)
+ // u o | o x o t
+ // ...
+ // u o o x | o t
+ {
+ a.take(input.element(o_qt));
+ o_qt += step;
+
+ a.untake(input.element(o_qu));
+ o_qu += step;
+
+ ++p_dir;
+ o_p += step;
+ output.element(o_p) = a.to_result();
+ }
+
+ // Go to the next line.
+ // --------------------
+
+ p_dir = pmin_dir;
+
+ for (int c = P::dim - 1; c >= 0; --c)
+ {
+ if (c == int(dir))
+ continue;
+ if (p[c] != pmax[c])
+ {
+ ++p[c];
+ break;
+ }
+ p[c] = pmin[c];
+ }
+
+ } while (p != pmin);
+
+ trace::exiting("accu::impl::transform_line_fastest");
+ return output;
+ }
+
+ /*
+
+ template <typename A, typename I>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_line_fastest_without_border(const Accumulator<A>& a_,
+ const Image<I>& input_,
+ unsigned length, unsigned dir)
+ {
+ trace::entering("accu::impl::transform_line_fastest_without_border");
+
+ const I& input = exact(input_);
+ A a = exact(a_);
+
+ internal::transform_line_tests(a, input);
+
+ mln_ch_value(I, mln_result(A)) output;
+ initialize(output, input);
+
+ typedef mln_psite(I) P;
+ const P
+ pmin = input.domain().pmin(),
pmax = input.domain().pmax();
const def::coord
- pmax_dir = pmax[dir],
+ pmax_dir = pmax[dir] - length / 2,
pmin_dir = pmin[dir];
P p = pmin; // Starting point.
def::coord& p_dir = p[dir];
+ // Step.
+ mln_delta(P) dp(literal::zero);
+ dp[dir] = 1;
+ int step = input.delta_index(dp);
+
do
{
- unsigned o_qu, o_qt;
+ // Start the line.
+ // ---------------
+
unsigned o_p = input.index_of_point(p);
+ unsigned o_qt = o_p;
+ unsigned o_qu = o_p;
- // Start the line.
- // ----------------
+ a.init();
- a.take_as_init(input.element(o_p));
- o_qu = o_p;
- for (unsigned i = 1; i <= length / 2; ++i)
+ // Causal part.
+ for (unsigned i = 0; i <= length / 2; ++i)
+ // | t
+ // | x t
+ // | x o t
{
- o_qu -= step;
- a.take(input.element(o_qu));
+ a.take(input.element(o_qt));
+ o_qt += step;
}
- o_qt = o_p;
- for (unsigned i = 1; i <= length / 2; ++i)
+ output.element(o_p) = a.to_result();
+
+ // Non-causal part.
+ for (unsigned i = 0; i < length / 2; ++i)
+ // | x o o <- end of previous loop
+ // | o x o t
+ // | o o x o t
{
- o_qt += step;
a.take(input.element(o_qt));
- }
+ o_qt += step;
+
+ ++p_dir;
+ o_p += step;
output.element(o_p) = a.to_result();
+ }
// Browse the line.
// ----------------
while (p_dir < pmax_dir)
+ // from .. o o x o o ..
+ // to .. u o o x o t ..
{
- ++p_dir;
-
- o_p += step;
+ a.take(input.element(o_qt));
o_qt += step;
- o_qu += step;
- a.take(input.element(o_qt));
a.untake(input.element(o_qu));
+ o_qu += step;
+ ++p_dir;
+ o_p += step;
output.element(o_p) = a.to_result();
}
- p_dir = pmin_dir;
+ // Finalize.
+ // ---------
+
+ for (unsigned i = 0; i < length / 2; ++i)
+ // o o x o o | <- end of previous loop
+ // u o o x o |
+ // u o o x |
+ {
+ a.untake(input.element(o_qu));
+ o_qu += step;
+
+ o_p += step;
+ output.element(o_p) = a.to_result();
+ }
// Go to the next line.
// --------------------
+ p_dir = pmin_dir;
+
for (int c = P::dim - 1; c >= 0; --c)
{
if (c == int(dir))
@@ -286,10 +421,11 @@
} while (p != pmin);
- trace::exiting("accu::impl::transform_line_fastest");
+ trace::exiting("accu::impl::transform_line_fastest_without_border");
return output;
}
+ */
} // end of namespace mln::accu::impl
@@ -306,6 +442,7 @@
inline
mln_ch_value(I, mln_result(A))
transform_line_dispatch(trait::image::speed::any,
+ trait::accumulator::when_pix::any,
const Accumulator<A>& a,
const Image<I>& input,
unsigned length, unsigned dir)
@@ -315,19 +452,45 @@
length, dir);
}
-// template <typename A, typename I>
-// inline
-// mln_ch_value(I, mln_result(A))
-// transform_line_dispatch(trait::image::speed::fastest,
-// const Accumulator<A>& a,
-// const Image<I>& input,
-// unsigned length, unsigned dir)
-// {
-// return impl::transform_line_fastest(a,
-// input,
-// length, dir);
-// }
+ template <typename A, typename I>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_line_dispatch(trait::image::speed::fastest,
+ trait::accumulator::when_pix::use_none,
+ const Accumulator<A>& a,
+ const Image<I>& input,
+ unsigned length, unsigned dir)
+ {
+ return impl::transform_line_fastest(a,
+ input,
+ length, dir);
+ }
+ template <typename A, typename I>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_line_dispatch(trait::image::speed::fastest,
+ trait::accumulator::when_pix::use_v,
+ const Accumulator<A>& a,
+ const Image<I>& input,
+ unsigned length, unsigned dir)
+ {
+ return impl::transform_line_fastest(a,
+ input,
+ length, dir);
+ }
+
+ template <typename A, typename I>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_line_dispatch(const Accumulator<A>& a,
+ const Image<I>& input,
+ unsigned length, unsigned dir)
+ {
+ return transform_line_dispatch(mln_trait_image_speed(I)(),
+ mln_trait_accumulator_when_pix(A)(),
+ a, input, length, dir);
+ }
} // end of namespace mln::accu::internal
@@ -348,10 +511,10 @@
internal::transform_line_tests(a, input);
- extension::adjust(input, length / 2);
+ extension::adjust(input, length / 2); // Safety.
+
mln_ch_value(I, mln_result(A)) output;
- output = internal::transform_line_dispatch(mln_trait_image_speed(I)(),
- a, input, length, dir);
+ output = internal::transform_line_dispatch(a, input, length, dir);
trace::exiting("accu::transform_line");
return output;
@@ -372,9 +535,8 @@
internal::transform_line_tests(a_, input);
- extension::adjust(input, length / 2);
mln_ch_value(I, mln_result(A_)) output;
- output = impl::generic::transform_line(a_, input, length, dir);
+ output = internal::transform_line_dispatch(a_, input, length, dir);
trace::exiting("accu::transform_line");
return output;
Index: milena/mln/accu/math/count.hh
--- milena/mln/accu/math/count.hh (revision 4351)
+++ milena/mln/accu/math/count.hh (working copy)
@@ -29,6 +29,8 @@
/// \file
///
/// Define an accumulator that counts.
+///
+/// \todo Add an optional parameter to set the type of the counter.
# include <mln/accu/internal/base.hh>
# include <mln/core/concept/meta_accumulator.hh>
@@ -37,18 +39,33 @@
namespace mln
{
- namespace accu
- {
+ // Forward declaration.
+ namespace accu {
+ namespace math {
+ template <typename T> struct count;
+ }
+ }
- namespace math
+
+ // Traits.
+
+ namespace trait
{
- // Forward declaration.
template <typename T>
- struct count;
+ struct accumulator_< accu::math::count<T> >
+ {
+ typedef accumulator::has_untake::yes has_untake;
+ typedef accumulator::has_set_value::yes has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_none when_pix;
+ };
+
+ } // end of namespace mln::trait
- } // end of namespace mln::accu::math
+ namespace accu
+ {
namespace meta
{
@@ -70,26 +87,6 @@
} // end of namespace mln::accu::meta
- } // end of namespace mln::accu
-
- // Traits.
- namespace trait
- {
-
- template <typename T>
- struct accumulator_< accu::math::count<T> >
- {
- typedef accumulator::has_untake::yes has_untake;
- typedef accumulator::has_set_value::yes has_set_value;
- typedef accumulator::has_stop::no has_stop;
- typedef accumulator::when_pix::use_pix when_pix;
- };
-
- } // end of namespace mln::trait
-
-
- namespace accu
- {
namespace math
{
@@ -132,9 +129,8 @@
};
-# ifndef MLN_INCLUDE_ONLY
-
+# ifndef MLN_INCLUDE_ONLY
template <typename T>
inline
Index: milena/mln/accu/logic/lor.hh
--- milena/mln/accu/logic/lor.hh (revision 4351)
+++ milena/mln/accu/logic/lor.hh (working copy)
@@ -39,14 +39,33 @@
namespace mln
{
- namespace accu
- {
-
- namespace logic
- {
// Forward declaration.
+ namespace accu {
+ namespace logic {
struct lor;
}
+ }
+
+
+ // Traits.
+
+ namespace trait
+ {
+
+ template <>
+ struct accumulator_< accu::logic::lor >
+ {
+ typedef accumulator::has_untake::yes has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace accu
+ {
namespace meta
{
Index: milena/mln/accu/logic/lor_basic.hh
--- milena/mln/accu/logic/lor_basic.hh (revision 4351)
+++ milena/mln/accu/logic/lor_basic.hh (working copy)
@@ -39,14 +39,33 @@
namespace mln
{
- namespace accu
- {
-
- namespace logic
- {
// Forward declaration.
+ namespace accu {
+ namespace logic {
struct lor_basic;
}
+ }
+
+
+ // Traits.
+
+ namespace trait
+ {
+
+ template <>
+ struct accumulator_< accu::logic::lor_basic >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::yes has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace accu
+ {
namespace meta
{
Index: milena/mln/accu/logic/land.hh
--- milena/mln/accu/logic/land.hh (revision 4351)
+++ milena/mln/accu/logic/land.hh (working copy)
@@ -39,14 +39,33 @@
namespace mln
{
- namespace accu
- {
-
- namespace logic
- {
// Forward declaration.
+ namespace accu {
+ namespace logic {
struct land;
}
+ }
+
+
+ // Traits.
+
+ namespace trait
+ {
+
+ template <>
+ struct accumulator_< accu::logic::land >
+ {
+ typedef accumulator::has_untake::yes has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace accu
+ {
namespace meta
{
@@ -66,6 +85,7 @@
} // end of namespace mln::accu::meta::logic
} // end of namespace mln::accu::meta
+
namespace logic
{
Index: milena/mln/accu/logic/land_basic.hh
--- milena/mln/accu/logic/land_basic.hh (revision 4351)
+++ milena/mln/accu/logic/land_basic.hh (working copy)
@@ -39,14 +39,33 @@
namespace mln
{
- namespace accu
- {
-
- namespace logic
- {
// Forward declaration.
+ namespace accu {
+ namespace logic {
struct land_basic;
}
+ }
+
+
+ // Traits.
+
+ namespace trait
+ {
+
+ template <>
+ struct accumulator_< accu::logic::land_basic >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::yes has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace accu
+ {
namespace meta
{
Index: milena/mln/accu/stat/min.hh
--- milena/mln/accu/stat/min.hh (revision 4351)
+++ milena/mln/accu/stat/min.hh (working copy)
@@ -39,17 +39,34 @@
namespace mln
{
- namespace accu
- {
- namespace stat
+ // Forward declaration.
+ namespace accu {
+ namespace stat {
+ template <typename T> struct min;
+ }
+ }
+
+
+ // Traits.
+
+ namespace trait
{
- // Forward declaration.
template <typename T>
- struct min;
+ struct accumulator_< accu::stat::min<T> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::yes has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
- } // end of namespace mln::accu::stat
+ } // end of namespace mln::trait
+
+
+ namespace accu
+ {
namespace meta
{
@@ -96,6 +113,9 @@
void take(const min<T>& other);
/// \}
+ /// Force the value of the min to \a t.
+ void set_value(const T& t);
+
/// Get the value of the accumulator.
const T& to_result() const;
@@ -155,6 +175,14 @@
template <typename T>
inline
+ void
+ min<T>::set_value(const T& t)
+ {
+ t_ = t;
+ }
+
+ template <typename T>
+ inline
const T&
min<T>::to_result() const
{
Index: milena/mln/accu/stat/max.hh
--- milena/mln/accu/stat/max.hh (revision 4351)
+++ milena/mln/accu/stat/max.hh (working copy)
@@ -39,19 +39,35 @@
namespace mln
{
- namespace accu
- {
- namespace stat
+ // Forward declaration.
+ namespace accu {
+ namespace stat {
+ template <typename T> struct max;
+ }
+ }
+
+
+ // Traits.
+
+ namespace trait
{
- // Forward declaration.
template <typename T>
- struct max;
+ struct accumulator_< accu::stat::max<T> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::yes has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
- } // end of namespace mln::accu::stat
+ } // end of namespace mln::trait
+ namespace accu
+ {
+
namespace meta
{
@@ -96,6 +112,9 @@
void take(const max<T>& other);
/// \}
+ /// Force the value of the min to \a t.
+ void set_value(const T& t);
+
/// Get the value of the accumulator.
const T& to_result() const;
@@ -111,6 +130,7 @@
template <typename I> struct max< util::pix<I> >;
+
# ifndef MLN_INCLUDE_ONLY
template <typename T>
@@ -156,6 +176,14 @@
template <typename T>
inline
+ void
+ max<T>::set_value(const T& t)
+ {
+ t_ = t;
+ }
+
+ template <typename T>
+ inline
const T&
max<T>::to_result() const
{
Index: milena/mln/accu/stat/min_h.hh
--- milena/mln/accu/stat/min_h.hh (revision 4351)
+++ milena/mln/accu/stat/min_h.hh (working copy)
@@ -39,17 +39,33 @@
namespace mln
{
- namespace accu
- {
+ // Forward declaration.
+ namespace accu {
+ namespace stat {
+ template <typename V> struct min_h;
+ }
+ }
- namespace stat
+
+ // Traits.
+
+ namespace trait
{
- // Forward declaration.
template <typename V>
- struct min_h;
+ struct accumulator_< accu::stat::min_h<V> >
+ {
+ typedef accumulator::has_untake::yes has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
- } // end of namespace mln::accu::stat
+ } // end of namespace mln::trait
+
+
+ namespace accu
+ {
namespace meta
{
Index: milena/mln/accu/stat/max_h.hh
--- milena/mln/accu/stat/max_h.hh (revision 4351)
+++ milena/mln/accu/stat/max_h.hh (working copy)
@@ -39,17 +39,33 @@
namespace mln
{
- namespace accu
- {
+ // Forward declaration.
+ namespace accu {
+ namespace stat {
+ template <typename V> struct max_h;
+ }
+ }
- namespace stat
+
+ // Traits.
+
+ namespace trait
{
- // Forward declaration.
template <typename V>
- struct max_h;
+ struct accumulator_< accu::stat::max_h<V> >
+ {
+ typedef accumulator::has_untake::yes has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_v when_pix;
+ };
+
+ } // end of namespace mln::trait
- } // end of namespace mln::accu::stat
+
+ namespace accu
+ {
namespace meta
{
@@ -114,15 +130,22 @@
mutable accu::histo<V> h_;
const value::set<V>& s_; // derived from h_
- mutable unsigned sum_;
- mutable bool valid_;
- mutable unsigned i_; // the max index
- mutable argument t_; // the max argument
+ mutable unsigned sum_; // number of taken values > t_
+ mutable unsigned i_; // the current max index ('current' means 'last
known')
+ mutable argument t_; // the current max argument
+
+ mutable bool valid_; // validity of the current indent / argument
+ // when valid_ is false, an update of i_ and t_ is required
+
+ // Dev note: we can have at the same time (sum_ == 0) and
+ // (valid_ == false) because of the 'untake' method.
// Auxiliary methods
void update_() const;
void go_minus_() const;
void go_plus_() const;
+
+ void invariant_() const;
};
@@ -132,11 +155,21 @@
template <typename V>
inline
+ void
+ max_h<V>::invariant_() const
+ {
+ // valid_ => (sum_ == 0)
+ mln_invariant(! valid_ || (sum_ == 0));
+ }
+
+ template <typename V>
+ inline
max_h<V>::max_h()
: h_(),
s_(h_.vset())
{
init();
+ invariant_();
}
template <typename V>
@@ -155,6 +188,7 @@
++sum_;
valid_ = false;
}
+ invariant_();
}
template <typename V>
@@ -166,8 +200,10 @@
h_.take(other.h_);
for (unsigned i = this->card() - 1; i > i_; --i)
sum_ += other.h_[i];
+ if (valid_ && sum_ != 0)
valid_ = false;
// FIXME: Optimize.
+ invariant_();
}
template <typename V>
@@ -191,6 +227,7 @@
else
if (t == t_ && h_[i_] == 0)
valid_ = false;
+ invariant_();
}
template <typename V>
@@ -204,6 +241,11 @@
if (h_[i_] == 0)
go_minus_();
valid_ = true;
+
+ mln_postcondition(sum_ == 0);
+ mln_postcondition(h_[i_] != 0);
+ for (unsigned j = i_ + 1; j < h_.nvalues(); ++j)
+ mln_postcondition(h_[j] == 0);
}
template <typename V>
@@ -263,6 +305,7 @@
{
if (! valid_)
update_();
+ invariant_();
return t_;
}
@@ -287,7 +330,7 @@
void
max_h<V>::debug_print_() const
{
- std::cout << "h={" << h_ << "} ";
+ std::cout << "h={" << h_ << "} h.sum = " <<
h_.sum() << ' ';
std::cout << "sum=" << sum_ << ' '
<< "valid=" << valid_ << ' '
<< "i=" << i_ << ' '
Index: milena/mln/morpho/general.spe.hh
--- milena/mln/morpho/general.spe.hh (revision 4351)
+++ milena/mln/morpho/general.spe.hh (working copy)
@@ -26,6 +26,22 @@
#ifndef MLN_MORPHO_GENERAL_SPE_HH
# define MLN_MORPHO_GENERAL_SPE_HH
+/// \file
+///
+/// Specialization for mln::morpho::general.
+///
+/// \todo Warning: we should also have the "arbitrary" versions working
+/// on sets (not only on functions!)
+///
+/// \todo HERE Factor dispatch for lines...
+///
+/// \todo Re-activate impl::line_on_function.
+///
+/// \todo Re-activate special code for centered window on sets.
+///
+/// \todo Dispatch transform_line when there is no extension to
+/// perform a side-effect.
+
# ifndef MLN_MORPHO_GENERAL_HH
# error "Forbidden inclusion of *.spe.hh"
# endif // ! MLN_MORPHO_GENERAL_HH
@@ -42,23 +58,6 @@
# include <mln/accu/transform_stop.hh>
# include <mln/accu/transform_diagonal.hh>
-# include <mln/accu/stat/min_h.hh>
-# include <mln/accu/line.hh>
-
-
-/// \file
-///
-/// Specialization for mln::morpho::general.
-///
-/// \todo Warning: we should also have the "arbitrary" versions working
-/// on sets (not only on functions!)
-///
-/// \todo HERE Factor dispatch for lines...
-///
-/// \todo Re-activate impl::line_on_function.
-///
-/// \todo Re-activate special code for centered window on sets.
-
# ifndef MLN_INCLUDE_ONLY
@@ -253,6 +252,7 @@
const W& win = exact(win_);
extension::adjust_fill(input, geom::delta(win), op.neutral(input));
+
mln_concrete(I) output;
output = accu::transform_line(op.accu_incr(input), input,
win.length(), win.dir);
Index: milena/tests/accu/transform_line.cc
--- milena/tests/accu/transform_line.cc (revision 4351)
+++ milena/tests/accu/transform_line.cc (working copy)
@@ -34,12 +34,15 @@
{
using namespace mln;
- image2d<unsigned> ima(4, 5);
- unsigned len = 3;
+ typedef unsigned T;
+ image2d<T> ima(4, 5);
+
+ typedef accu::math::count<T> A;
+ const unsigned len = 31;
for (unsigned dir = 0; dir < 2; ++dir)
{
- image2d<unsigned> out = accu::transform_line(accu::meta::math::count(), ima,
len, dir);
- mln_assertion(out == (pw::cst(3u) | ima.domain()));
+ image2d<unsigned> out = accu::impl::transform_line_fastest(A(), ima, len,
dir);
+ mln_assertion(out == (pw::cst(len) | ima.domain()));
+ mln_assertion(accu::impl::generic::transform_line(A(), ima, len, dir) == out);
}
-
}