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(a)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