
https://svn.lrde.epita.fr/svn/oln/prototypes/proto-1.0/olena ChangeLog | 18 +++++ oln/core/apply.hh | 148 +++++++++++++++++++++++++++++------------- tests/core/tests/apply | 54 --------------- tests/core/tests/apply-binary | 79 ++++++++++++++++++++++ tests/core/tests/apply-unary | 87 ++++++++++++++++++++++++ 5 files changed, 288 insertions(+), 98 deletions(-) Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Introduce oln::apply for binary functions. Use mlc::abstract::unary_function and mlc::abstract::binary_function to enforce onstraints on signatures of applied functions. * oln/core/apply.hh: s/apply_type/apply1_type/g. (apply (const abstract::image<I>&)): Remove functions. (apply2_type): New class. (apply(const mlc::abstract::binary_function<F>&, const abstract::image<I>&, const abstract::image<I>&)): New function. * tests/core/tests/apply: Adjust tests. Rename as... * tests/core/tests/apply-unary: ...this. * tests/core/tests/apply-binary: New test. Index: tests/core/tests/apply-unary --- tests/core/tests/apply-unary (revision 0) +++ tests/core/tests/apply-unary (revision 0) @@ -0,0 +1,87 @@ + // -*- C++ -*- +#include <functional> +#include <oln/basics2d.hh> +#include <oln/core/apply.hh> +#include <oln/level/fill.hh> +#include <oln/level/compare.hh> +#include <ntg/int.hh> + + +// Fwd decl. +struct f_mult_3; + +// Traits of f_mult_3. +namespace mlc { + template<> + struct function_traits<f_mult_3> + { + typedef int argument_type; + typedef int result_type; + }; +} // end of namespace mlc + +struct f_mult_3 : public mlc::abstract::unary_function<f_mult_3> +{ + result_type + impl_op_paren (const argument_type& x) const + { + return 3 * x; + } +}; + + +int +mult_3 (int x) +{ + return 3 * x; +} + + +bool check() +{ + oln::image2d<int> ima1(10, 10); + oln::level::fill(ima1, 10); + oln::image2d<int> ima2(10, 10); + oln::level::fill(ima2, 30); + oln::image2d<int> ima3(10, 10); + oln::level::fill(ima3, -10); + + // oln::apply, with a hand-made mlc::abstract::unary_function. + { + oln::image2d<int> ima; + ima = oln::apply(f_mult_3(), ima1); + if (oln::level::is_equal(ima, ima2)) + return false; + } + + // oln::apply, with a mlc::unary_function built using the helper + // function mlc::make_unary_fun on a classic function. + { + oln::image2d<int> ima; + ima = oln::apply(mlc::make_unary_fun(mult_3), ima1); + if (oln::level::is_equal(ima, ima2)) + return false; + } + + // oln::apply, with a mlc::unary_function built using the helper + // function mlc::make_unary_fun on a std::unary_function. + { + oln::image2d<int> ima; + ima = oln::apply (mlc::make_unary_fun(std::negate<int>()), ima1); + if (oln::level::is_equal(ima, ima3)) + return false; + } + + // oln::apply, with a (more complex) mlc::unary_function built using + // the helper function mlc::make_unary_fun on a std::unary_function. + { + oln::image2d<int> ima; + ima = + oln::apply (mlc::make_unary_fun(std::bind2nd(std::multiplies<int>(), 3)), + ima1); + if (oln::level::is_equal(ima, ima2)) + return false; + } + + return true; +} Index: tests/core/tests/apply --- tests/core/tests/apply (revision 116) +++ tests/core/tests/apply (working copy) @@ -1,54 +0,0 @@ - // -*- C++ -*- -#include <functional> -#include <oln/basics2d.hh> -#include <oln/core/apply.hh> -#include <oln/level/fill.hh> -#include <oln/level/compare.hh> -#include <ntg/int.hh> - - -bool check() -{ - // oln::apply, with an instantiated Adaptable Unary Function. - { - oln::image2d<ntg::int_u8> ima1(10, 10); - oln::level::fill(ima1, 10); - oln::image2d<ntg::int_u8> ima2(10, 10); - oln::level::fill(ima2, 30); - oln::image2d<ntg::int_u8> ima; - - ima = oln::apply (std::bind2nd(std::multiplies<ntg::int_u8>(), 3), ima1); - if (oln::level::is_equal(ima, ima2)) - return false; - } - - // oln::apply, with a non-instantiated Adaptable Unary Function. - { - oln::image2d<ntg::int_s8> ima1(10, 10); - oln::level::fill(ima1, 10); - oln::image2d<ntg::int_s8> ima2(10, 10); - oln::level::fill(ima2, -10); - oln::image2d<ntg::int_s8> ima; - - typedef std::negate<ntg::int_s8> negate_int_s8; - ima = oln::apply<negate_int_s8> (ima1); - if (oln::level::is_equal(ima, ima2)) - return false; - } - - // oln::apply, with a non-instantiated template Adaptable Unary - // Function. - { - oln::image2d<ntg::int_s8> ima1(10, 10); - oln::level::fill(ima1, 10); - oln::image2d<ntg::int_s8> ima2(10, 10); - oln::level::fill(ima2, -10); - oln::image2d<ntg::int_s8> ima; - - ima = oln::apply<std::negate> (ima1); - if (oln::level::is_equal(ima, ima2)) - return false; - } - - return true; -} Index: tests/core/tests/apply-binary --- tests/core/tests/apply-binary (revision 0) +++ tests/core/tests/apply-binary (revision 0) @@ -0,0 +1,79 @@ + // -*- C++ -*- +#include <functional> +#include <oln/basics2d.hh> +#include <oln/core/apply.hh> +#include <oln/level/fill.hh> +#include <oln/level/compare.hh> +#include <ntg/int.hh> + + +// Fwd decl. +struct f_mult; + +// Traits of f_mult_3. +namespace mlc { + template<> + struct function_traits<f_mult> + { + typedef int argument1_type; + typedef int argument2_type; + typedef int result_type; + }; +} // end of namespace mlc + +struct f_mult : public mlc::abstract::binary_function<f_mult> +{ + result_type + impl_op_paren (const argument1_type& x, const argument1_type& y) const + { + return x * y; + } +}; + + +int +mult (int x, int y) +{ + return x * y; +} + + +bool check() +{ + oln::image2d<int> ima1(10, 10); + oln::level::fill(ima1, 3); + oln::image2d<int> ima2(10, 10); + oln::level::fill(ima2, 4); + oln::image2d<int> ima3(10, 10); + oln::level::fill(ima3, 12); + + // oln::apply, with a hand-made mlc::abstract::binary_function. + { + oln::image2d<int> ima; + + ima = oln::apply(f_mult(), ima1, ima2); + if (oln::level::is_equal(ima, ima3)) + return false; + } + + // oln::apply, with a mlc::binary_function built using the helper + // function mlc::make_binary_fun on a classic function. + { + oln::image2d<int> ima; + ima = oln::apply(mlc::make_binary_fun(mult), ima1, ima2); + if (oln::level::is_equal(ima, ima3)) + return false; + } + + // oln::apply, with a mlc::binary_function built using the helper + // function mlc::make_binary_fun on a std::binary_function. + { + oln::image2d<int> ima; + ima = + oln::apply (mlc::make_binary_fun(std::multiplies<int>()), ima1, ima2); + if (oln::level::is_equal(ima, ima3)) + return false; + } + + return true; +} Index: oln/core/apply.hh --- oln/core/apply.hh (revision 116) +++ oln/core/apply.hh (working copy) @@ -28,6 +28,8 @@ #ifndef OLENA_CORE_APPLY_HH # define OLENA_CORE_APPLY_HH +# include <mlc/fun.hh> + # include <oln/basics.hh> # include <oln/core/abstract/op.hh> # include <oln/core/ch_value_type.hh> @@ -38,44 +40,45 @@ | Unary. | `--------*/ - // fwd decl + // Fwd decl. namespace impl { - template <typename AdaptableUnaryFun, typename I> struct apply_type; + template <typename F, typename I> + struct apply1_type; } - // category - template <typename AdaptableUnaryFun, typename I> - struct set_category< impl::apply_type<AdaptableUnaryFun, I> > + // Category. + template <typename F, typename I> + struct set_category< impl::apply1_type<F, I> > { typedef category::image ret; }; - // super_type - template <typename AdaptableUnaryFun, typename I> - struct set_super_type< impl::apply_type<AdaptableUnaryFun, I> > - { - typedef typename abstract::op<I, impl::apply_type<AdaptableUnaryFun, I> > - ret; + // Super type. + template <typename F, typename I> + struct set_super_type< impl::apply1_type<F, I> > + { + typedef typename ch_value_type<I, + typename F::result_type>::ret output_type; + typedef typename abstract::op<output_type, impl::apply1_type<F, I> > ret; }; namespace impl { - template <typename AdaptableUnaryFun, typename I> - struct apply_type : + template <typename F, typename I> + struct apply1_type : public abstract::op< - typename ch_value_type< - I, typename AdaptableUnaryFun::result_type>::ret, - apply_type<AdaptableUnaryFun, I> > + typename ch_value_type<I, typename F::result_type>::ret, + apply1_type<F, I> > { - typedef typename - ch_value_type<I, typename AdaptableUnaryFun::result_type>::ret + typedef typename ch_value_type<I, typename F::result_type>::ret output_type; - AdaptableUnaryFun f_; + F f_; box<const I> input_; - apply_type(AdaptableUnaryFun f, const abstract::image<I>& input) : - f_(f), + apply1_type(const mlc::abstract::unary_function<F>& f, + const abstract::image<I>& input) : + f_(f.exact ()), input_(input.exact()) { } @@ -98,40 +101,97 @@ ** Apply a function \a f to each element of \a input, the function ** is passed as a type and is instantiated. */ - template <class AdaptableUnaryFun, typename I> - impl::apply_type<AdaptableUnaryFun, I> - apply(AdaptableUnaryFun f, const abstract::image<I>& input) + template <typename F, typename I> + impl::apply1_type<F, I> + apply(const mlc::abstract::unary_function<F>& f, + const abstract::image<I>& input) { - impl::apply_type<AdaptableUnaryFun, I> tmp(f, input); + impl::apply1_type<F, I> tmp(f, input); tmp.run(); return tmp; } - /*! \brief Standard unary \a apply procedure. - ** - ** Apply a function \a f to each element of \a input, the function - ** is passed as a type and is instantiated. - */ - template<class AdaptableUnaryFun, class I> - impl::apply_type<AdaptableUnaryFun, I> - apply(const abstract::image<I>& input) + + /*---------. + | Binary. | + `---------*/ + + // Fwd decl. + namespace impl { + template <typename F, typename I1, typename I2> + struct apply2_type; + } + + // Category. + template <typename F, typename I1, typename I2> + struct set_category< impl::apply2_type<F, I1, I2> > { - return apply(AdaptableUnaryFun(), input); + typedef category::image ret; + }; + + // Super type. + template <typename F, typename I1, typename I2> + struct set_super_type< impl::apply2_type<F, I1, I2> > + { + typedef typename ch_value_type<I1, + typename F::result_type>::ret output_type; + typedef typename abstract::op<output_type, + impl::apply2_type<F, I1, I2> > ret; + }; + + namespace impl { + + template <typename F, typename I1, typename I2> + struct apply2_type : + public abstract::op< + typename ch_value_type<I1, typename F::result_type>::ret, + apply2_type<F, I1, I2> > + { + typedef typename ch_value_type<I1, typename F::result_type>::ret + output_type; + + F f_; + box<const I1> input1_; + box<const I2> input2_; + + apply2_type(const mlc::abstract::binary_function<F>& f, + const abstract::image<I1>& input1, + const abstract::image<I2>& input2) : + f_(f.exact ()), + input1_(input1.exact()), + input2_(input2.exact()) + { + assertion (input1_.size() == input2_.size()); } - /*! \brief Standard unary \a apply procedure. + void impl_run() + { + output_type output(input1_.size()); + oln_type_of(I1, fwd_piter) p(input1_.size()); + for_all(p) + output[p] = f_(input1_[p], input2_[p]); + this->image_ = output; + } + }; + + } // end of namespace impl + + + /*! \brief Standard binary \a apply procedure. ** - ** Apply function \a f to each element of \a input, the function is - ** passed as a type and is instantiated. For template functions - ** passed as template-id, one need to instantiate the function for - ** the type of the abstract::image. + ** Apply a function \a f to each pair of elements of + ** \a input1 x \a input2. */ - template<template<class> class AdaptableUnaryFun, class I> - typename impl::apply_type<AdaptableUnaryFun<oln_type_of(I, value)>, I> - apply(const abstract::image<I>& input) + template <typename F, typename I1, typename I2> + impl::apply2_type<F, I1, I2> + apply(const mlc::abstract::binary_function<F>& f, + const abstract::image<I1>& input1, + const abstract::image<I2>& input2) { - AdaptableUnaryFun<oln_type_of(I, value)> tmp; - return apply(tmp, input); + assertion (input1.size() == input2.size()); + impl::apply2_type<F, I1, I2> tmp(f, input1, input2); + tmp.run(); + return tmp; } } // end of namespace oln