cleanup-2008 2558: Update dispatch in the transform algo according to image properties.

https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Nicolas Ballas <ballas@lrde.epita.fr> Update dispatch in the transform algo according to image properties. * tests/level/transform.cc: Add tests. * mln/trait/image/props.hh: Fix a mistakes. * mln/level/transform.spe.hh: Add dispatch. * mln/level/transform.hh: Add transform_tests function. mln/level/transform.hh | 44 +++++- mln/level/transform.spe.hh | 312 ++++++++++++++++++++++++++++++++++++++++----- mln/trait/image/props.hh | 3 tests/level/transform.cc | 59 +++++++- 4 files changed, 378 insertions(+), 40 deletions(-) Index: tests/level/transform.cc --- tests/level/transform.cc (revision 2558) +++ tests/level/transform.cc (working copy) @@ -33,9 +33,14 @@ #include <cmath> #include <mln/core/image/image2d.hh> +#include <mln/core/image/flat_image.hh> +#include <mln/core/image/image_if.hh> + #include <mln/level/transform.hh> #include <mln/debug/iota.hh> +#include <mln/core/var.hh> +#include <mln/fun/p2b/chess.hh> struct mysqrt : mln::Function_v2v<mysqrt> { @@ -51,12 +56,11 @@ int main() { using namespace mln; - const unsigned size = 1000; - image2d<unsigned short> - ima(size, size); - image2d<unsigned short> - out(size, size); + + { + image2d<unsigned short> ima(size, size); + image2d<unsigned short> out(size, size); (std::cout << "iota... ").flush(); debug::iota(ima); @@ -72,3 +76,48 @@ mln_assertion((unsigned short)std::sqrt(ima(p)) == out(p)); std::cout << "done" << std::endl; } + + { + flat_image<short, box2d> ima(5, make::box2d(size, size)); + image2d<unsigned short> out(size, size); + + (std::cout << "fill... ").flush(); + level::fill_with_value(ima, 51); + std::cout << "done" << std::endl; + + (std::cout << "transform... ").flush(); + level::transform(ima, mysqrt(), out); + std::cout << "done" << std::endl; + + (std::cout << "checking... ").flush(); + box2d::piter p(out.domain()); + for_all(p) + mln_assertion((unsigned short)std::sqrt(ima(p)) == out(p)); + std::cout << "done" << std::endl; + } + + { + typedef image2d<unsigned short> I; + typedef image_if<I, fun::p2b::chess_t> II; + + I ima(size, size); + I out(size, size); + II ima_if = ima | fun::p2b::chess; + + level::fill_with_value(ima, 0); + (std::cout << "iota... ").flush(); + debug::iota(ima); + std::cout << "done" << std::endl;; + + (std::cout << "transform... ").flush(); + level::transform(ima_if, mysqrt(), out); + std::cout << "done" << std::endl; + + (std::cout << "checking... ").flush(); + II::piter p(ima_if.domain()); + for_all(p) + mln_assertion((unsigned short)std::sqrt(ima_if(p)) == out(p)); + std::cout << "done" << std::endl; + } + +} Index: mln/trait/image/props.hh --- mln/trait/image/props.hh (revision 2558) +++ mln/trait/image/props.hh (working copy) @@ -424,7 +424,8 @@ { struct any { protected: any() {} }; struct some : any { protected: some() {} }; - struct none : any { protected: none() {} }; + struct none + : any { std::string name() const { return "vw_set::none";} }; struct uni : some { std::string name() const { return "vw_set::uni";} }; struct multi Index: mln/level/transform.spe.hh --- mln/level/transform.spe.hh (revision 2558) +++ mln/level/transform.spe.hh (working copy) @@ -41,6 +41,8 @@ # include <mln/core/concept/image.hh> # include <mln/core/concept/function.hh> +# include <mln/level/fill_with_value.hh> + # include <mln/value/set.hh> # include <mln/value/lut_vec.hh> @@ -54,7 +56,18 @@ namespace level { + namespace internal + { + template <typename I, typename F, typename O> + inline + void transform_tests(const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output); + } + + // Implementation + // -------------- namespace impl { @@ -62,58 +75,295 @@ namespace generic { template <typename I, typename F, typename O> - void transform_(const Image<I>& input_, const Function_v2v<F>& f_, Image<O>& output_); + void transform(const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_); } + + template <typename I, typename F, typename O> - inline - void transform_(mln::trait::image::quant::any, // general case - const Image<I>& input_, const Function_v2v<F>& f_, Image<O>& output_) + void transform_lowq(const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_) { - generic::transform_(input_, f_, output_); - } + trace::entering("level::impl::transform_lowq"); + + const I& input = exact(input_); + const F& f = exact(f_); + O& output = exact(output_); + level::internal::transform_tests(input, f, output); + mlc_is(mln_trait_image_pw_io(O), + trait::image::pw_io::read_write)::check(); + + value::lut_vec<mln_vset(I), mln_result(F)> + lut(input.values_eligible(), f); + + mln_piter(I) p(input.domain()); + for_all(p) + output(p) = lut(input(p)); + + trace::exiting("level::impl::transform_lowq"); + } template <typename I, typename F, typename O> - inline - void transform_(mln::trait::image::quant::low, // low quantization - const Image<I>& input_, const Function_v2v<F>& f_, Image<O>& output_) + void transform_taken(const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_) { - trace::entering("level::impl::transform"); + trace::entering("level::impl::transform_taken"); const I& input = exact(input_); const F& f = exact(f_); O& output = exact(output_); - value::lut_vec<mln_vset(I), mln_result(F)> lut(input.values_eligible(), f); + level::internal::transform_tests(input, f, output); + mlc_is(mln_trait_image_pw_io(O), + trait::image::pw_io::read_write)::check(); + + value::lut_vec<mln_vset(I), mln_result(F)> + lut(input.taken_values(), f); + mln_piter(I) p(input.domain()); for_all(p) output(p) = lut(input(p)); - trace::exiting("level::impl::transform"); + trace::exiting("level::impl::transform_taken"); + } + + + template <typename I, typename F, typename O> + void transform_singleton(const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_) + { + trace::entering("level::impl::transform_singleton"); + + const I& input = exact(input_); + const F& f = exact(f_); + + level::internal::transform_tests(input_, f_, output_); + mln_precondition((mlc_is(mln_trait_image_pw_io(O), + trait::image::pw_io::read_write)::value || + mlc_is(mln_trait_image_vw_io(O), + trait::image::vw_io::read_write)::value)); + + mln_result(F) val = f(input.val()); + fill_with_value(output_, val); + + trace::exiting("level::impl::transform_singleton"); + } + + template <typename I, typename F, typename O> + void transform_fast(const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_) + { + trace::entering("level::impl::transform_fast"); + + const I& input = exact(input_); + const F& f = exact(f_); + O& output = exact(output_); + + level::internal::transform_tests(input, f, output); + + mln_pixter(const I) pi(input); + mln_pixter(O) po(output); + + po.start(); + for_all(pi) + { + po.val() = f(pi.val()); } + trace::exiting("level::impl::transform_fast"); + } + + + + template <typename I, typename F, typename O> + void transform_fast_lowq(const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_) + { + trace::entering("level::impl::transform_fast_lowq"); + + const I& input = exact(input_); + const F& f = exact(f_); + O& output = exact(output_); + + level::internal::transform_tests(input, f, output); + + value::lut_vec<mln_vset(I), mln_result(F)> + lut(input.values_eligible(), f); + + mln_pixter(const I) pi(input); + mln_pixter(O) po(output); + + po.start(); + for_all(pi) + { + //po.val() = lut(pi.val); + po.val() = f(pi.val()); + } + + trace::exiting("level::impl::transform_fast_lowq"); + } + + + + // Dispatch + // -------- + namespace internal + { + + /// Deal with image not updated + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::undef, + mln::trait::image::quant::any, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + impl::generic::transform(input, f, output); + } + + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::image::vw_set::any, + mln::trait::image::quant::any, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + impl::generic::transform(input, f, output); + } + + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::image::vw_set::uni, + mln::trait::image::quant::any, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + impl::transform_taken(input, f, output); + } + + + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::image::vw_set::none, + mln::trait::image::quant::low, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + impl::transform_lowq(input, f, output); + } + + template <typename I, typename F, typename O> + void transform_dispatch_oneblock(mln::trait::image::quant::any, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + transform_fast(input, f, output); + } + + template <typename I, typename F, typename O> + void transform_dispatch_oneblock(mln::trait::image::quant::low, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + transform_fast_lowq(input, f, output); + } + + + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::image::value_storage::any, + mln::trait::image::value_storage::any, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + transform_dispatch(mln_trait_image_vw_set(I)(), + mln_trait_image_quant(I)(), + input, f, output); + } + + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::image::value_storage::singleton, + mln::trait::image::value_storage::any, + const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + transform_singleton(input, f, output); + } + + template <typename I, typename F, typename O> + void transform_dispatch(mln::trait::image::value_storage::one_block, + mln::trait::image::value_storage::one_block, + const Image<I>& input_, + const Function_v2v<F>& f_, + Image<O>& output_) + { + const I& input = exact(input_); + O& output = exact(output_); + + /// Check basic properties + if (mlc_is(mln_trait_image_value_access(O), + trait::image::value_access::direct)::value && + mlc_is(mln_trait_image_value_access(I), + trait::image::value_access::direct)::value && + mlc_is(mln_trait_image_value_alignement(I), + trait::image::value_alignement::with_grid)::value && + mlc_is(mln_trait_image_value_alignement(O), + trait::image::value_alignement::with_grid)::value) + { + /// Check ext_domain + if ( + ((mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::fixed)::value || + mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::extendable)::value) && + (mlc_is(mln_trait_image_ext_domain(O), + trait::image::ext_domain::fixed)::value || + mlc_is(mln_trait_image_ext_domain(O), + trait::image::ext_domain::extendable)::value) && + input.border() == output.border()) || + (mlc_is(mln_trait_image_ext_domain(I), + trait::image::ext_domain::none)::value && + mlc_is(mln_trait_image_ext_domain(O), + trait::image::ext_domain::none)::value)) + { + + /// Check domain + if (input.domain() == output.domain()) + transform_dispatch_oneblock(mln_trait_image_quant(I)(), + input, f_, output); + } + } + transform_dispatch(mln_trait_image_vw_set(I)(), + mln_trait_image_quant(I)(), + input, f_, output); + } + + + + template <typename I, typename F, typename O> + void transform_dispatch(const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + transform_dispatch(mln_trait_image_value_storage(I)(), + mln_trait_image_value_storage(O)(), + input, f, output); + } + + } - // FIXME: Handle the cases of fastest images. -// template <typename I, typename F, typename O> -// void transform(metal::true_, // low quantization -// const Image<I>& input_, const Function_v2v<F>& f_, Image<O>& output_) -// { -// const I& input = exact(input_); -// const F& f = exact(f_); -// O& output = exact(output_); - -// value::lut_vec<mln_vset(I), mln_result(F)> lut(input.values(), f); -// mln_pixter(const I) pi(input); // FIXME -// mln_pixter(O) po(output); -// po.start(); -// for_all(pi) -// { -// po.val() = lut(pi.val()); -// po.next(); -// } -// } } // end of namespace mln::level::impl Index: mln/level/transform.hh --- mln/level/transform.hh (revision 2558) +++ mln/level/transform.hh (working copy) @@ -76,23 +76,61 @@ # ifndef MLN_INCLUDE_ONLY + namespace internal + { + template <typename I, typename F, typename O> + inline + void transform_tests(const Image<I>& input, + const Function_v2v<F>& f, + Image<O>& output) + { + // Avoid a warning about an undefined variable when NDEBUG + // is not defined. + (void) input; + (void) f; + (void) output; + + // Properties check + mln_precondition((mlc_is(mln_trait_image_pw_io(O), + trait::image::pw_io::read_write)::value || + mlc_is(mln_trait_image_vw_io(O), + trait::image::vw_io::read_write)::value)); + + // FIXME Convert test + mlc_converts_to(mln_result(F), mln_value(O))::check(); + + + // Dynamic tests + mln_precondition(exact(input).has_data()); + mln_precondition(exact(output).domain() >= exact(input).domain()); + } + } // end of namespace mln::level::internal + + namespace impl { + namespace generic { + // Generic implementation. template <typename I, typename F, typename O> inline - void transform_(const Image<I>& input_, const Function_v2v<F>& f_, + void transform(const Image<I>& input_, const Function_v2v<F>& f_, Image<O>& output_) { trace::entering("level::impl::generic::transform"); + const I& input = exact(input_); const F& f = exact(f_); O& output = exact(output_); + level::internal::transform_tests(input, f, output); + mlc_is(mln_trait_image_pw_io(O), + trait::image::pw_io::read_write)::check(); + mln_piter(I) p(input.domain()); for_all(p) output(p) = f( input(p) ); @@ -115,8 +153,8 @@ trace::entering("level::transform"); mln_precondition(exact(output).domain() >= exact(input).domain()); - impl::transform_(mln_trait_image_quant(I)(), - exact(input), exact(f), exact(output)); + impl::internal::transform_dispatch(exact(input), exact(f), + exact(output)); trace::exiting("level::transform"); }
participants (1)
-
Nicolas Ballas