4352: Fix various accumulators things.

https://svn.lrde.epita.fr/svn/oln/trunk Index: ChangeLog from Thierry Geraud <thierry.geraud@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); } - }
participants (1)
-
Thierry Geraud