Commit 6a20ee2b authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Fix image expression.

parent 410de38e
...@@ -42,26 +42,34 @@ namespace mln { ...@@ -42,26 +42,34 @@ namespace mln {
/**** Implementation ****/ /**** Implementation ****/
/******************************************/ /******************************************/
namespace impl
{
template <typename I, typename J>
void paste(const I& ima, J& out)
{
mln_pixter(px, ima);
mln_forall(px)
out(px->point()) = px->val();
}
}
template <typename InputImage, typename OutputImage> template <typename InputImage, typename OutputImage>
OutputImage& OutputImage&
paste(const Image<InputImage>& input, Image<OutputImage>& output_) paste(const Image<InputImage>& input, Image<OutputImage>& output_)
{ {
paste(input, fwd_exact(output_)); impl::paste(exact(input), exact(output_));
return exact(output_); return exact(output_);
} }
template <typename InputImage, typename OutputImage> template <typename InputImage, typename OutputImage>
OutputImage&& OutputImage&&
paste(const Image<InputImage>& input_, Image<OutputImage>&& output_) paste(const Image<InputImage>& input_, Image<OutputImage>&& output_)
{ {
OutputImage&& output = fwd_exact(output_); paste(input_, output_);
for (auto px: exact(input_).pixels()) return move_exact(output_);
output(px.point()) = px.val();
return std::forward<OutputImage>(output);
} }
......
...@@ -4,6 +4,38 @@ ...@@ -4,6 +4,38 @@
# include <type_traits> # include <type_traits>
# include <string> # include <string>
namespace internal
{
template <bool cond, typename T>
struct mln_check_if_
{
mln_check_if_() {}
};
template <typename T>
struct mln_check_if_<true, T>
{
mln_check_if_() { ((T*)0)->~T(); }
};
}
# define MLN_CONCEPT_BEGIN_CHECK_IF() \
{ \
struct __mln_check_if__ \
{ \
~__mln_check_if__() \
{ \
# define MLN_CONCEPT_END_CHECK_IF(TEST) \
} \
}; \
internal::mln_check_if_<TEST, __mln_check_if__> (); \
}
namespace mln namespace mln
{ {
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
namespace mln { namespace mln {
template <typename I> struct Image;
template <typename I> struct IterableImage;
template <typename I> template <typename I>
struct Image : Object_<I> struct Image : Object_<I>
...@@ -48,7 +50,12 @@ namespace mln { ...@@ -48,7 +50,12 @@ namespace mln {
BOOST_CONCEPT_ASSERT((Pixel<pixel>)); BOOST_CONCEPT_ASSERT((Pixel<pixel>));
BOOST_CONCEPT_ASSERT((Pixel<const_pixel>)); BOOST_CONCEPT_ASSERT((Pixel<const_pixel>));
MLN_CONCEPT_BEGIN_CHECK_IF()
BOOST_CONCEPT_ASSERT((IterableImage<I>));
MLN_CONCEPT_END_CHECK_IF((std::is_convertible<category, forward_image_tag>::value))
check(std::is_convertible<pixel, const_pixel> ()); check(std::is_convertible<pixel, const_pixel> ());
} }
}; };
...@@ -131,6 +138,9 @@ namespace mln { ...@@ -131,6 +138,9 @@ namespace mln {
check(std::is_same<typename pixel_type::image_type, I> ()); check(std::is_same<typename pixel_type::image_type, I> ());
check(std::is_same<typename const_pixel_type::image_type, const I> ()); check(std::is_same<typename const_pixel_type::image_type, const I> ());
check(std::is_convertible<value_iterator, const_value_iterator> ());
check(std::is_convertible<pixel_iterator, const_pixel_iterator> ());
} }
}; };
......
...@@ -133,19 +133,19 @@ namespace mln ...@@ -133,19 +133,19 @@ namespace mln
// The expression is a rvalue, need to copy // The expression is a rvalue, need to copy
template <typename ColExpr> template <typename ColExpr>
struct should_copy_col_<ColExpr&&> struct should_copy_col_
{ {
typedef ColExpr type; typedef ColExpr type;
static ColExpr&& static ColExpr
copy(ColExpr&& col) { return std::move<ColExpr>(col); } copy(ColExpr& col) { return std::move(col); }
}; };
template <typename ColExpr> template <typename ColExpr>
typename should_copy_col_<ColExpr>::type typename should_copy_col_<ColExpr>::type
should_copy_col(ColExpr&& x) should_copy_col(ColExpr&& x)
{ {
return should_copy_col_<ColExpr>::copy(std::forward<ColExpr>(x)); return should_copy_col_<ColExpr>::copy(x);
} }
} }
...@@ -155,6 +155,12 @@ namespace mln ...@@ -155,6 +155,12 @@ namespace mln
# define __mln_should_copy_col__(COL, ID) \ # define __mln_should_copy_col__(COL, ID) \
decltype(mln::internal::should_copy_col(COL)) ID = mln::internal::should_copy_col(COL) decltype(mln::internal::should_copy_col(COL)) ID = mln::internal::should_copy_col(COL)
# define __mln_should_copy_col_local__(COL, ID) \
if (mln::internal::false_var_t< decltype(mln::internal::should_copy_col(COL)) > ID = \
{mln::internal::should_copy_col(COL)}) {} else
/******************************************/ /******************************************/
/**** mln_viter *****/ /**** mln_viter *****/
...@@ -268,5 +274,15 @@ namespace mln ...@@ -268,5 +274,15 @@ namespace mln
# define __mln_do_local__(EXPR) \
if ((EXPR), false) {} else
# define mln_foreach(p, COL) \
__mln_should_copy_col_local__(COL, _mln_range_) \
MLN_DECL_VAR(_mln_it_, _mln_range_.get().iter()) \
for (_mln_it_.get().init(); !_mln_it_.get().finished(); _mln_it_.get().next()) \
if (bool _mln_continue_ = false) {} else \
for (p = *(_mln_it_.get()); !_mln_continue_; _mln_continue_ = true) \
#endif //!MLN_CORE_FORALL_HPP #endif //!MLN_CORE_FORALL_HPP
#ifndef FUNCTIONAL_HPP
# define FUNCTIONAL_HPP
# include <functional>
namespace mln
{
//
// contrary to std::bind, it can be DefaultConstructible and Assignable
template <typename BinaryFunction, typename V>
struct binder1st
{
private:
BinaryFunction fun_;
V v_;
public:
binder1st() = default;
binder1st(const BinaryFunction& f, const V& v)
: fun_(f), v_ (v)
{
}
template <typename T>
typename std::result_of< BinaryFunction(V, T) >::type
operator () (T&& x) const
{
return fun_(v_, std::forward<T>(x));
}
};
template <typename BinaryFunction, typename V>
struct binder2nd
{
private:
BinaryFunction fun_;
V v_;
public:
binder2nd() = default;
binder2nd(const BinaryFunction& f, const V& v)
: fun_(f), v_ (v)
{
}
template <typename T>
typename std::result_of< BinaryFunction(T, V) >::type
operator () (T&& x) const
{
return fun_(std::forward<T>(x), v_);
}
};
template <typename BinaryFunction, typename V>
inline
binder1st<BinaryFunction, V>
bind1st(const BinaryFunction& f, const V& v)
{
return binder1st<BinaryFunction, V>(f, v);
}
template <typename BinaryFunction, typename V>
inline
binder2nd<BinaryFunction, V>
bind2nd(const BinaryFunction& f, const V& v)
{
return binder2nd<BinaryFunction, V>(f, v);
}
}
#endif // ! FUNCTIONAL_HPP
#ifndef MLN_CORE_IMAGE_IMAGE_EXPR_HPP #ifndef MLN_CORE_IMAGE_IMAGE_EXPR_HPP
# define MLN_CORE_IMAGE_IMAGE_EXPR_HPP # define MLN_CORE_IMAGE_IMAGE_EXPR_HPP
# include <mln/core/functional.hpp>
# include <mln/core/concept/image.hpp> # include <mln/core/concept/image.hpp>
# include <mln/core/image/zip_image.hpp> # include <mln/core/image/zip_image.hpp>
...@@ -28,9 +30,9 @@ namespace mln ...@@ -28,9 +30,9 @@ namespace mln
template <typename BinaryFunction, typename Scalar, typename Image> template <typename BinaryFunction, typename Scalar, typename Image>
struct binary_scalar_image_expr; struct binary_scalar_image_expr;
template <typename UnaryFunction, typename I> // template <typename UnaryFunction, typename I>
unary_image_expr<UnaryFunction, I> // unary_image_expr<UnaryFunction, I>
make_unary_image_expr(I&& ima, UnaryFunction f); // make_unary_image_expr(I&& ima, UnaryFunction f);
...@@ -59,34 +61,34 @@ namespace mln ...@@ -59,34 +61,34 @@ namespace mln
template <typename UnaryFunction, typename I> template <typename UnaryFunction, typename I>
unary_image_expr<UnaryFunction, I> unary_image_expr<UnaryFunction, I>
make_unary_image_expr(I&& ima, UnaryFunction f) make_unary_image_expr(I&& ima, const UnaryFunction& f)
{ {
BOOST_CONCEPT_ASSERT((Image<typename std::remove_reference<I>::type>)); BOOST_CONCEPT_ASSERT((Image<typename std::decay<I>::type>));
return unary_image_expr<UnaryFunction, I>(std::forward<I>(ima), f); return unary_image_expr<UnaryFunction, I>(std::forward<I>(ima), f);
} }
template <typename BinaryFunction, typename I1, typename I2> template <typename BinaryFunction, typename I1, typename I2>
binary_image_expr<BinaryFunction, I1, I2> binary_image_expr<BinaryFunction, I1, I2>
make_binary_image_expr(I1&& ima1, I2&& ima2, BinaryFunction f) make_binary_image_expr(I1&& ima1, I2&& ima2, const BinaryFunction& f)
{ {
BOOST_CONCEPT_ASSERT((Image<typename std::remove_reference<I1>::type>)); BOOST_CONCEPT_ASSERT((Image<typename std::decay<I1>::type>));
BOOST_CONCEPT_ASSERT((Image<typename std::remove_reference<I2>::type>)); BOOST_CONCEPT_ASSERT((Image<typename std::decay<I2>::type>));
return binary_image_expr<BinaryFunction, I1, I2>(std::forward<I1>(ima1), std::forward<I2>(ima2), f); return binary_image_expr<BinaryFunction, I1, I2>(std::forward<I1>(ima1), std::forward<I2>(ima2), f);
} }
template <typename BinaryFunction, typename I, typename Scalar> template <typename BinaryFunction, typename I, typename Scalar>
binary_image_scalar_expr<BinaryFunction, I, Scalar> binary_image_scalar_expr<BinaryFunction, I, Scalar>
make_binary_image_scalar_expr(I&& ima, const Scalar& x, BinaryFunction f) make_binary_image_scalar_expr(I&& ima, const Scalar& x, const BinaryFunction& f)
{ {
BOOST_CONCEPT_ASSERT((Image<typename std::remove_reference<I>::type>)); BOOST_CONCEPT_ASSERT((Image<typename std::decay<I>::type>));
return binary_image_scalar_expr<BinaryFunction, I, Scalar>(std::forward<I>(ima), x, f); return binary_image_scalar_expr<BinaryFunction, I, Scalar>(std::forward<I>(ima), x, f);
} }
template <typename BinaryFunction, typename Scalar, typename I> template <typename BinaryFunction, typename Scalar, typename I>
binary_scalar_image_expr<BinaryFunction, Scalar, I> binary_scalar_image_expr<BinaryFunction, Scalar, I>
make_binary_scalar_image_expr(const Scalar& x, I&& ima, BinaryFunction f) make_binary_scalar_image_expr(const Scalar& x, I&& ima, const BinaryFunction& f)
{ {
BOOST_CONCEPT_ASSERT((Image<typename std::remove_reference<I>::type>)); BOOST_CONCEPT_ASSERT((Image<typename std::decay<I>::type>));
return binary_scalar_image_expr<BinaryFunction, Scalar, I>(x, std::forward<I>(ima), f); return binary_scalar_image_expr<BinaryFunction, Scalar, I>(x, std::forward<I>(ima), f);
} }
...@@ -188,7 +190,7 @@ namespace mln ...@@ -188,7 +190,7 @@ namespace mln
typedef iterator_range<const_value_iterator> const_value_range; typedef iterator_range<const_value_iterator> const_value_range;
typedef iterator_range<const_pixel_iterator> const_pixel_range; typedef iterator_range<const_pixel_iterator> const_pixel_range;
unary_image_expr_base(Image&& ima_, UnaryFunction f_): unary_image_expr_base(Image&& ima_, const UnaryFunction& f_):
ima (std::forward<Image>(ima_)), ima (std::forward<Image>(ima_)),
f (f_) f (f_)
{ {
...@@ -233,14 +235,14 @@ namespace mln ...@@ -233,14 +235,14 @@ namespace mln
pixel_range pixel_range
pixels() pixels()
{ {
pixel_iterator x(ima.pixels().iter(), f); pixel_iterator x(f, ima.pixels().iter(), exact(*this));
return make_iterator_range(x); return make_iterator_range(x);
} }
const_pixel_range const_pixel_range
pixels() const pixels() const
{ {
const_pixel_iterator x(ima.pixels().iter(), f); const_pixel_iterator x(f, ima.pixels().iter(), exact(*this));
return make_iterator_range(x); return make_iterator_range(x);
} }
...@@ -258,7 +260,10 @@ namespace mln ...@@ -258,7 +260,10 @@ namespace mln
{ {
typedef typename std::result_of<Function (U, V)>::type result_type; typedef typename std::result_of<Function (U, V)>::type result_type;
wrap_tuple_to_arg(Function f_) wrap_tuple_to_arg() = default;
wrap_tuple_to_arg(const Function& f_)
: f(f_) : f(f_)
{ {
} }
...@@ -289,7 +294,7 @@ namespace mln ...@@ -289,7 +294,7 @@ namespace mln
typedef internal::unary_image_expr_base< F, zip_image<Image1, Image2>, binary_image_expr<BinaryFunction, Image1, Image2> > base_t; typedef internal::unary_image_expr_base< F, zip_image<Image1, Image2>, binary_image_expr<BinaryFunction, Image1, Image2> > base_t;
public: public:
binary_image_expr(Image1&& ima1, Image2&& ima2, BinaryFunction f): binary_image_expr(Image1&& ima1, Image2&& ima2, const BinaryFunction& f):
base_t( imzip(std::forward<Image1>(ima1), std::forward<Image2>(ima2)), F(f) ) base_t( imzip(std::forward<Image1>(ima1), std::forward<Image2>(ima2)), F(f) )
{ {
} }
...@@ -300,7 +305,7 @@ namespace mln ...@@ -300,7 +305,7 @@ namespace mln
struct unary_image_expr : internal::unary_image_expr_base< UnaryFunction, Image, unary_image_expr<UnaryFunction, Image> > struct unary_image_expr : internal::unary_image_expr_base< UnaryFunction, Image, unary_image_expr<UnaryFunction, Image> >
{ {
unary_image_expr(Image&& ima, UnaryFunction f): unary_image_expr(Image&& ima, const UnaryFunction& f):
internal::unary_image_expr_base< UnaryFunction, Image, unary_image_expr<UnaryFunction, Image> >(std::forward<Image>(ima), f) internal::unary_image_expr_base< UnaryFunction, Image, unary_image_expr<UnaryFunction, Image> >(std::forward<Image>(ima), f)
{ {
} }
...@@ -309,14 +314,14 @@ namespace mln ...@@ -309,14 +314,14 @@ namespace mln
template <typename BinaryFunction, typename Image, typename Scalar> template <typename BinaryFunction, typename Image, typename Scalar>
struct binary_image_scalar_expr : struct binary_image_scalar_expr :
internal::unary_image_expr_base< std::binder2nd<BinaryFunction>, Image, binary_image_scalar_expr<BinaryFunction, Image, Scalar> > internal::unary_image_expr_base< mln::binder2nd<BinaryFunction, Scalar>, Image, binary_image_scalar_expr<BinaryFunction, Image, Scalar> >
{ {
private: private:
typedef internal::unary_image_expr_base< std::binder2nd<BinaryFunction>, Image, binary_image_scalar_expr<BinaryFunction, Image, Scalar> > base_t; typedef internal::unary_image_expr_base< mln::binder2nd<BinaryFunction, Scalar>, Image, binary_image_scalar_expr<BinaryFunction, Image, Scalar> > base_t;
public: public:
binary_image_scalar_expr(Image&& ima, const Scalar& x, BinaryFunction f): binary_image_scalar_expr(Image&& ima, const Scalar& x, const BinaryFunction& f):
base_t(std::forward<Image>(ima), std::bind2nd(f, x)) base_t(std::forward<Image>(ima), mln::bind2nd(f, x))
{ {
} }
}; };
...@@ -324,14 +329,14 @@ namespace mln ...@@ -324,14 +329,14 @@ namespace mln
template <typename BinaryFunction, typename Scalar, typename Image> template <typename BinaryFunction, typename Scalar, typename Image>
struct binary_scalar_image_expr struct binary_scalar_image_expr
: internal::unary_image_expr_base< std::binder1st<BinaryFunction>, Image, binary_scalar_image_expr<BinaryFunction,Scalar,Image> > : internal::unary_image_expr_base< mln::binder1st<BinaryFunction, Scalar>, Image, binary_scalar_image_expr<BinaryFunction,Scalar,Image> >
{ {
private: private:
typedef internal::unary_image_expr_base< std::binder1st<BinaryFunction>, Image, binary_scalar_image_expr<BinaryFunction, Scalar, Image> > base_t; typedef internal::unary_image_expr_base< mln::binder1st<BinaryFunction, Scalar>, Image, binary_scalar_image_expr<BinaryFunction, Scalar, Image> > base_t;
public: public:
binary_scalar_image_expr(const Scalar& x, Image&& ima, BinaryFunction f): binary_scalar_image_expr(const Scalar& x, Image&& ima, const BinaryFunction& f):
base_t(std::forward<Image>(ima), std::bind1st(f, x)) base_t(std::forward<Image>(ima), mln::bind1st(f, x))
{ {
} }
}; };
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# include <mln/core/image/image_expr.hpp> # include <mln/core/image/image_expr.hpp>
# include <mln/core/ops.hpp> # include <mln/core/ops.hpp>
#include <iostream>
namespace mln namespace mln
{ {
/// \defgroup ima_ops Image operators /// \defgroup ima_ops Image operators
...@@ -116,8 +116,10 @@ namespace mln ...@@ -116,8 +116,10 @@ namespace mln
static_assert(std::is_convertible<typename I::value_type, bool>::value, static_assert(std::is_convertible<typename I::value_type, bool>::value,
"Image value type must be convertible to bool"); "Image value type must be convertible to bool");
for(bool v : exact(ima).values()) mln_viter(v, exact(ima));
if (!v) return false; mln_forall(v)
if (!*v) return false;
return true; return true;
} }
...@@ -130,8 +132,10 @@ namespace mln ...@@ -130,8 +132,10 @@ namespace mln
static_assert(std::is_convertible<typename I::value_type, bool>::value, static_assert(std::is_convertible<typename I::value_type, bool>::value,
"Image value type must be convertible to bool"); "Image value type must be convertible to bool");
for(bool v : exact(ima).values()) mln_viter(v, exact(ima));
if (v) return true; mln_forall(v)
if (*v) return true;
return false; return false;
} }
......
...@@ -375,6 +375,15 @@ namespace mln ...@@ -375,6 +375,15 @@ namespace mln
{ {
} }
template <typename PointVisitor2, typename ValueVisitor2, typename InternalStruct2>
nested_loop_iterator(const nested_loop_iterator<PointVisitor2, ValueVisitor2, InternalStruct2, DereferencePolicy>& other,
typename std::enable_if< std::is_convertible<PointVisitor, PointVisitor2>::value and
std::is_convertible<ValueVisitor2, ValueVisitor>::value and
std::is_convertible<InternalStruct2, InternalStruct>::value>::type* = NULL)
: s_ (other.s_), p_ (other.p_), v_ (other.v_)
{
}
void init() void init()
{ {
...@@ -401,7 +410,7 @@ namespace mln ...@@ -401,7 +410,7 @@ namespace mln
private: private:
template <typename, typename, typename, typename> template <typename, typename, typename, typename>
friend struct nested_loop_iterator_forward; friend struct nested_loop_iterator;
enum { ndim = PointVisitor::point_type::ndim }; enum { ndim = PointVisitor::point_type::ndim };
......