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

Fix image expression.

parent 410de38e
......@@ -42,26 +42,34 @@ namespace mln {
/**** 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>
OutputImage&
paste(const Image<InputImage>& input, Image<OutputImage>& output_)
{
paste(input, fwd_exact(output_));
impl::paste(exact(input), exact(output_));
return exact(output_);
}
template <typename InputImage, typename OutputImage>
OutputImage&&
paste(const Image<InputImage>& input_, Image<OutputImage>&& output_)
{
OutputImage&& output = fwd_exact(output_);
for (auto px: exact(input_).pixels())
output(px.point()) = px.val();
return std::forward<OutputImage>(output);
paste(input_, output_);
return move_exact(output_);
}
......
......@@ -4,6 +4,38 @@
# include <type_traits>
# 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
{
......
......@@ -13,6 +13,8 @@
namespace mln {
template <typename I> struct Image;
template <typename I> struct IterableImage;
template <typename I>
struct Image : Object_<I>
......@@ -48,7 +50,12 @@ namespace mln {
BOOST_CONCEPT_ASSERT((Pixel<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> ());
}
};
......@@ -131,6 +138,9 @@ namespace mln {
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_convertible<value_iterator, const_value_iterator> ());
check(std::is_convertible<pixel_iterator, const_pixel_iterator> ());
}
};
......
......@@ -133,19 +133,19 @@ namespace mln
// The expression is a rvalue, need to copy
template <typename ColExpr>
struct should_copy_col_<ColExpr&&>
struct should_copy_col_
{
typedef ColExpr type;
static ColExpr&&
copy(ColExpr&& col) { return std::move<ColExpr>(col); }
static ColExpr
copy(ColExpr& col) { return std::move(col); }
};
template <typename ColExpr>
typename should_copy_col_<ColExpr>::type
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
# define __mln_should_copy_col__(COL, ID) \
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 *****/
......@@ -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
#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
# define MLN_CORE_IMAGE_IMAGE_EXPR_HPP
# include <mln/core/functional.hpp>
# include <mln/core/concept/image.hpp>
# include <mln/core/image/zip_image.hpp>
......@@ -28,9 +30,9 @@ namespace mln
template <typename BinaryFunction, typename Scalar, typename Image>
struct binary_scalar_image_expr;
template <typename UnaryFunction, typename I>
unary_image_expr<UnaryFunction, I>
make_unary_image_expr(I&& ima, UnaryFunction f);
// template <typename UnaryFunction, typename I>
// unary_image_expr<UnaryFunction, I>
// make_unary_image_expr(I&& ima, UnaryFunction f);
......@@ -59,34 +61,34 @@ namespace mln
template <typename UnaryFunction, typename 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);
}
template <typename BinaryFunction, typename I1, typename 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::remove_reference<I2>::type>));
BOOST_CONCEPT_ASSERT((Image<typename std::decay<I1>::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);
}
template <typename BinaryFunction, typename I, typename 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);
}
template <typename BinaryFunction, typename Scalar, typename 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);
}
......@@ -188,7 +190,7 @@ namespace mln
typedef iterator_range<const_value_iterator> const_value_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_)),
f (f_)
{
......@@ -233,14 +235,14 @@ namespace mln
pixel_range
pixels()
{
pixel_iterator x(ima.pixels().iter(), f);
pixel_iterator x(f, ima.pixels().iter(), exact(*this));
return make_iterator_range(x);
}
const_pixel_range
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);
}
......@@ -258,7 +260,10 @@ namespace mln
{
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_)
{
}
......@@ -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;
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) )
{
}
......@@ -300,7 +305,7 @@ namespace mln
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)
{
}
......@@ -309,14 +314,14 @@ namespace mln
template <typename BinaryFunction, typename Image, typename Scalar>
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:
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:
binary_image_scalar_expr(Image&& ima, const Scalar& x, BinaryFunction f):
base_t(std::forward<Image>(ima), std::bind2nd(f, x))
binary_image_scalar_expr(Image&& ima, const Scalar& x, const BinaryFunction& f):
base_t(std::forward<Image>(ima), mln::bind2nd(f, x))
{
}
};
......@@ -324,14 +329,14 @@ namespace mln
template <typename BinaryFunction, typename Scalar, typename Image>
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:
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:
binary_scalar_image_expr(const Scalar& x, Image&& ima, BinaryFunction f):
base_t(std::forward<Image>(ima), std::bind1st(f, x))
binary_scalar_image_expr(const Scalar& x, Image&& ima, const BinaryFunction& f):
base_t(std::forward<Image>(ima), mln::bind1st(f, x))
{
}
};
......
......@@ -3,7 +3,7 @@
# include <mln/core/image/image_expr.hpp>
# include <mln/core/ops.hpp>
#include <iostream>
namespace mln
{
/// \defgroup ima_ops Image operators
......@@ -116,8 +116,10 @@ namespace mln
static_assert(std::is_convertible<typename I::value_type, bool>::value,
"Image value type must be convertible to bool");
for(bool v : exact(ima).values())
if (!v) return false;
mln_viter(v, exact(ima));
mln_forall(v)
if (!*v) return false;
return true;
}
......@@ -130,8 +132,10 @@ namespace mln
static_assert(std::is_convertible<typename I::value_type, bool>::value,
"Image value type must be convertible to bool");
for(bool v : exact(ima).values())
if (v) return true;
mln_viter(v, exact(ima));
mln_forall(v)
if (*v) return true;
return false;
}
......
......@@ -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()
{
......@@ -401,7 +410,7 @@ namespace mln
private:
template <typename, typename, typename, typename>
friend struct nested_loop_iterator_forward;
friend struct nested_loop_iterator;
enum { ndim = PointVisitor::point_type::ndim };
......
......@@ -63,9 +63,6 @@ namespace mln
ndimage_pixel<const T, dim, const E>
>
{
BOOST_CONCEPT_ASSERT((IterableImage<E>));
BOOST_CONCEPT_ASSERT((AccessibleImage<E>));
private:
typedef ndimage_base<T, dim, E> this_type;
public:
......
......@@ -54,7 +54,7 @@ namespace mln
{
template <class Range> struct apply
{
typedef typename range_iterator< std::remove_reference<Range> >::type type;
typedef typename range_iterator< typename std::remove_reference<Range>::type >::type type;
};
template <typename Range>
......
......@@ -59,7 +59,7 @@ namespace mln
# include <mln/core/forall.hpp>
//# include <mln/core/image/image_expr.hpp>
//# include <mln/core/image/image_ops.hpp>
# include <mln/core/image/image_expr.hpp>
# include <mln/core/image/image_ops.hpp>
#endif //!MLN_CORE_IMAGE_BASE_HPP
......@@ -34,13 +34,28 @@ namespace mln {
{
}
template <typename PointIterator2, typename ValueIterator2, typename Image2>
zip_point_value_pixel(const zip_point_value_pixel<PointIterator2, ValueIterator2, Image2>& other,
typename std::enable_if<std::is_convertible<PointIterator2, PointIterator>::value and
std::is_convertible<ValueIterator2, ValueIterator>::value and
std::is_convertible<Image2*, Image*>::value>::type* = NULL)
: pit_ (other.pit_), vit_ (other.vit_), ima_ (other.ima_)
{
}
point_type point() const { return *pit_; }
point_type site() const { return *pit_; }
reference val() const { return *vit_; }
image_type& image() const { return *ima_; }
friend class pixel_iterator<PointIterator, ValueIterator, Image>;
private:
template <typename, typename, typename>
friend struct zip_point_value_pixel;
PointIterator pit_;
ValueIterator vit_;
Image* ima_;
......@@ -56,6 +71,14 @@ namespace mln {
pixel_iterator() = default;
pixel_iterator(const pixel_iterator&) = default;
template <typename SiteSetIterator2, typename ValueIterator2, typename Image2>
pixel_iterator(const pixel_iterator<SiteSetIterator2, ValueIterator2, Image2>& other,
typename std::enable_if< std::is_convertible<typename pixel_iterator<SiteSetIterator2, ValueIterator2, Image2>::pixel_t,
pixel_t>::value >::type* = NULL)
: pixel_ (other.pixel_)
{
}
pixel_iterator(const SiteSetIterator& pit,
const ValueIterator& vit,
Image& ima)
......@@ -77,6 +100,9 @@ namespace mln {
// }
private:
template <typename, typename, typename>
friend struct pixel_iterator;
pixel_t pixel_;
};
......
......@@ -35,17 +35,29 @@ namespace mln
{
typedef typename internal::transform_iterator_helper<Iterator, UnaryFunction, Reference, Value>::reference reference;
transform_iterator() = default;
transform_iterator(const Iterator& it, const UnaryFunction& f)
: it_ (it), f_ (f)
{
}
template <typename Iterator2, typename Reference2, typename Value2>
transform_iterator(const transform_iterator<Iterator2, UnaryFunction, Reference2, Value2>& other,
typename std::enable_if<std::is_convertible<Iterator2, Iterator>::value>::type* = NULL)
: it_ (other.it_), f_ (other.f_)
{
}
void init() { it_.init(); }
void next() { it_.next(); }
bool finished() const { return it_.finished(); }
reference dereference() const { return f_(*it_); }
private:
template <typename, typename, typename, typename>
friend struct transform_iterator;
Iterator it_;
UnaryFunction f_;
};
......
......@@ -11,7 +11,7 @@ namespace mln
struct transformed_pixel;
template <typename UnaryFunction, typename PixelIterator, typename Image>
struct transformed_pixel_iterator;
struct transform_pixel_iterator;
/***********************/
......@@ -41,7 +41,7 @@ namespace mln
template <typename PixelIterator2, typename Image2>
transformed_pixel(const transformed_pixel<UnaryFunction, PixelIterator2, Image2>& other,
typename std::enable_if< std::is_convertible<PixelIterator2, PixelIterator>::value and
std::is_convertible<Image2*, Image*>::value >::type* = NULL)
std::is_convertible<Image2*, Image*>::value >::type* = NULL)
: x_ (other.x_), fun_ (other.fun_), ima_ (other.ima_)
{
}
......@@ -95,6 +95,16 @@ namespace mln
{
}
template <typename PixelIterator2, typename Image2>
transform_pixel_iterator(const transform_pixel_iterator<UnaryFunction, PixelIterator2, Image2>& other,
typename std::enable_if<std::is_convertible<
typename transform_pixel_iterator<UnaryFunction, PixelIterator2, Image2>::pixel_t,