Commit 99fb0c80 authored by Michaël Roynard's avatar Michaël Roynard Committed by Michaël Roynard
Browse files

WIP: adaptor/transform

parent d5e6fd6b
Pipeline #12682 failed with stages
in 4 minutes and 19 seconds
......@@ -91,9 +91,9 @@ namespace mln::archetypes
using view = std::true_type;
ViewImage() = delete;
ViewImage(const ViewImage&) = delete;
ViewImage(const ViewImage&) = default;
ViewImage(ViewImage&&) = default;
ViewImage& operator=(const ViewImage&) = delete;
ViewImage& operator=(const ViewImage&) = default;
ViewImage& operator=(ViewImage&&) = default;
};
......
......@@ -14,6 +14,12 @@ namespace mln::archetypes
using point_type = Point;
using reference = const value_type&;
Pixel() = delete;
Pixel(const Pixel&) = default;
Pixel(Pixel&&) = default;
Pixel& operator=(const Pixel&) = default;
Pixel& operator=(Pixel&&) = default;
point_type point() const;
reference val() const;
};
......
......@@ -24,7 +24,7 @@
namespace mln::concepts
{
// clang-format off
// clang-format off
#ifdef PYLENE_CONCEPT_TS_ENABLED
......@@ -33,6 +33,7 @@ namespace mln::concepts
concept Image =
// FIXME: inheritance from New_Image required for the moment
stl::Movable<Ima> && // Minimum constraint on image object
stl::Copyable<Ima> && // Do not requires DefaultConstructible
stl::DerivedFrom<image_category_t<Ima>, forward_image_tag> &&
requires {
typename image_pixel_t<Ima>;
......
......@@ -18,7 +18,8 @@ namespace mln::concepts
// Pixel
template<typename Pix>
concept Pixel =
stl::Semiregular<Pix> &&
stl::Movable<Pix> && // Minimum constraint on pixel object
stl::Copyable<Pix> && // Do not requires DefaultConstructible
requires {
typename pixel_value_t<Pix>;
typename pixel_reference_t<Pix>;
......
......@@ -37,8 +37,8 @@ namespace mln
struct image2d : ndimage_base<T, 2, image2d<T>>
{
private:
typedef ndimage_base<T, 2, image2d<T>> base_type;
typedef ndimage_base<T, 2, image2d<T>> base;
using base_type = ndimage_base<T, 2, image2d<T>>;
using base = ndimage_base<T, 2, image2d<T>>;
public:
typedef typename base_type::domain_type domain_type;
......@@ -48,10 +48,6 @@ namespace mln
using base::base;
// Required because of a MS bug
// (https://developercommunity.visualstudio.com/content/problem/47799/vc-default-constructor-deleted.html)
image2d() = default;
image2d(short nrows, short ncols, unsigned border = 3, const T& init = T())
: base(box<short, 2>{{0, 0}, {nrows, ncols}}, border, init)
{
......@@ -86,7 +82,7 @@ namespace mln
for (const std::initializer_list<T>& row : l)
{
mln_assertion(row.size() == nc);
for (const T *val = row.begin(); val != row.end(); ++val, v.next())
for (const T* val = row.begin(); val != row.end(); ++val, v.next())
*v = *val;
}
}
......
......@@ -38,12 +38,13 @@ namespace mln
struct image3d : ndimage_base<T, 3, image3d<T>>
{
private:
typedef ndimage_base<T, 3, image3d<T>> base_type;
typedef ndimage_base<T, 3, image3d<T>> base;
using base_type = ndimage_base<T, 3, image3d<T>>;
using base = ndimage_base<T, 3, image3d<T>>;
public:
typedef typename base_type::domain_type domain_type;
using domain_type = typename base_type::domain_type;
using base::base;
explicit image3d(unsigned border = 3)
: ndimage_base<T, 3, image3d<T>>(border)
......@@ -94,7 +95,7 @@ namespace mln
for (const auto& row : slice)
{
mln_assertion(row.size() == nc);
for (const T *val = row.begin(); val != row.end(); ++val, v.next())
for (const T* val = row.begin(); val != row.end(); ++val, v.next())
*v = *val;
}
}
......
......@@ -32,6 +32,18 @@ namespace mln::details
using value_type = std::remove_const_t<T>;
using reference = T&;
ndpix_base(T* ptr, point_type pnt)
: m_lineptr(ptr)
, m_point(pnt)
{
}
ndpix_base() = default;
ndpix_base(const ndpix_base&) = default;
ndpix_base(ndpix_base&&) = default;
ndpix_base& operator=(const ndpix_base&) = default;
ndpix_base& operator=(ndpix_base&&) = default;
reference val() const { return m_lineptr[m_point[N - 1]]; }
point_type point() const { return m_point; }
......
......@@ -14,21 +14,26 @@ namespace mln
template <class Pixel>
struct pixel_adaptor
{
using point_type = typename Pixel::point_type;
using site_type[[deprecated]] = point_type;
using value_type = typename Pixel::value_type;
using reference = typename Pixel::reference;
using point_type = typename Pixel::point_type;
using site_type [[deprecated]] = point_type;
using value_type = typename Pixel::value_type;
using reference = typename Pixel::reference;
decltype(auto) val() const { return m_pix.val(); }
auto point() const { return m_pix.point(); }
void advance(point_type p) { m_pix.advance(p); }
pixel_adaptor() = default;
pixel_adaptor(Pixel px)
: m_pix{std::move(px)}
{
}
// no default constructor as Pixel may not be default constructible
pixel_adaptor(const pixel_adaptor&) = default;
pixel_adaptor(pixel_adaptor&&) = default;
pixel_adaptor& operator=(const pixel_adaptor&) = default;
pixel_adaptor& operator=(pixel_adaptor&&) = default;
protected:
Pixel& base() { return m_pix; }
const Pixel& base() const { return m_pix; }
......@@ -77,8 +82,8 @@ namespace mln
template <class I>
struct image_adaptor_base_indexable<I, std::enable_if_t<I::indexable::value>>
{
using size_type[[deprecated]] = image_index_t<I>;
using index_type = size_type;
using size_type [[deprecated]] = image_index_t<I>;
using index_type = size_type;
};
template <class I, class = void>
......@@ -130,11 +135,17 @@ namespace mln
// Image proxy //
/////////////////
image_adaptor(I ima)
explicit image_adaptor(I ima)
: m_ima(std::move(ima))
{
}
// no default constructor as I may not be default constructible
image_adaptor(const image_adaptor<I>&) = default;
image_adaptor(image_adaptor<I>&&) = default;
image_adaptor<I>& operator=(const image_adaptor<I>&) = default;
image_adaptor<I>& operator=(image_adaptor<I>&&) = default;
auto domain() const { return m_ima.domain(); }
auto new_values() { return m_ima.new_values(); }
auto new_pixels() { return m_ima.new_pixels(); }
......
......@@ -12,8 +12,8 @@ namespace mln
template <class I, class F>
class transform_view : public image_adaptor<I>, public New_Image<transform_view<I, F>>
{
using fun_t = F; // FIXME something with semiregular_t<F> ?
fun_t f;
using fun_t = F;
fun_t fun_;
public:
/// Type definitions
......@@ -55,27 +55,93 @@ namespace mln
using reference = transform_view::reference;
using value_type = transform_view::value_type;
new_pixel_type() = default;
new_pixel_type(F fun, image_pixel_t<I> px)
new_pixel_type(fun_t fun, image_pixel_t<I> px)
: new_pixel_type::pixel_adaptor{px}
, f{fun}
, fun_{fun}
{
}
new_pixel_type(const new_pixel_type& other)
: new_pixel_type::pixel_adaptor{other}
, fun_(other.fun_)
{
}
new_pixel_type(new_pixel_type&& other)
: new_pixel_type::pixel_adaptor{std::move(other)}
, fun_(std::move(other.fun_))
{
}
new_pixel_type& operator=(const new_pixel_type& other)
{
if (this != &other)
{
new_pixel_type::pixel_adaptor::operator=(other);
fun_ = other.fun_;
}
return *this;
}
new_pixel_type& operator=(new_pixel_type&& other)
{
if (this != &other)
{
new_pixel_type::pixel_adaptor::operator=(std::move(other));
fun_ = std::move(other.fun_);
}
return *this;
}
reference val() const { return std::invoke(f, this->base().val()); }
reference val() const { return std::invoke(fun_, this->base().val()); }
private:
fun_t f;
fun_t fun_;
};
/// \}
transform_view(I ima, F fun)
: transform_view::image_adaptor{std::move(ima)}
, f{std::move(fun)}
, fun_{std::move(fun)}
{
}
transform_view(const transform_view& other)
: transform_view::image_adaptor{other}
, fun_(other.fun_)
{
}
transform_view(transform_view&& other)
: transform_view::image_adaptor{std::move(other)}
, fun_(std::move(other.fun_))
{
}
transform_view& operator=(const transform_view& other)
{
if (this != &other)
{
transform_view::image_adaptor::operator=(other);
fun_ = other.fun_;
}
return *this;
}
transform_view& operator=(transform_view&& other)
{
if (this != &other)
{
transform_view::image_adaptor::operator=(std::move(other));
fun_ = std::move(other.fun_);
}
return *this;
}
decltype(auto) concretize() const { return imchvalue<value_type>(this->base()); }
template <class U>
......@@ -84,12 +150,12 @@ namespace mln
return imchvalue<U>(this->base());
}
auto new_values() { return mln::ranges::view::transform(this->base().new_values(), f); }
auto new_values() { return mln::ranges::view::transform(this->base().new_values(), fun_); }
auto new_pixels()
{
using R = decltype(this->base().new_pixels());
auto pxwrapper = [fun = this->f](::ranges::range_value_t<R> px) { return new_pixel_type{fun, std::move(px)}; };
auto pxwrapper = [fun = this->fun_](::ranges::range_value_t<R> px) { return new_pixel_type{fun, std::move(px)}; };
return mln::ranges::view::transform(this->base().new_pixels(), pxwrapper);
}
......@@ -97,32 +163,32 @@ namespace mln
std::enable_if_t<accessible::value, dummy> operator()(point_type p)
{
mln_precondition(this->base().domain().has(p));
return std::invoke(f, this->base()(p));
return std::invoke(fun_, this->base()(p));
}
template <typename dummy = reference>
std::enable_if_t<accessible::value, dummy> at(point_type p)
{
return std::invoke(f, this->base().at(p));
return std::invoke(fun_, this->base().at(p));
}
template <typename dummy = new_pixel_type>
std::enable_if_t<accessible::value, dummy> new_pixel(point_type p)
{
mln_precondition(this->base().domain().has(p));
return {f, this->base().new_pixel(p)};
return {fun_, this->base().new_pixel(p)};
}
template <typename dummy = new_pixel_type>
std::enable_if_t<accessible::value, dummy> new_pixel_at(point_type p)
{
return {f, this->base().new_pixel_at(p)};
return {fun_, this->base().new_pixel_at(p)};
}
template <typename dummy = I>
reference operator[](typename dummy::size_type i)
{
return std::invoke(f, this->base()[i]);
return std::invoke(fun_, this->base()[i]);
}
};
......@@ -132,7 +198,7 @@ namespace mln
using fun_t = F; // FIXME something with semiregular_t<F> ?
I1 m_ima1;
I2 m_ima2;
fun_t f;
fun_t fun_;
public:
/// Type definitions
......@@ -162,22 +228,22 @@ namespace mln
struct new_pixel_type : Pixel<new_pixel_type>
{
public:
using point_type = typename transform2_view::point_type;
using site_type[[deprecated]] = point_type;
using value_type = typename transform2_view::value_type;
using reference = typename transform2_view::reference;
using point_type = typename transform2_view::point_type;
using site_type [[deprecated]] = point_type;
using value_type = typename transform2_view::value_type;
using reference = typename transform2_view::reference;
new_pixel_type() = default;
new_pixel_type(fun_t fun, image_pixel_t<I1> px1, image_pixel_t<I2> px2)
: m_pix1{std::move(px1)}
, m_pix2{std::move(px2)}
, f{std::move(fun)}
, fun_{std::move(fun)}
{
}
// FIXME: implement copy/move ctors/operators
reference val() const { return std::invoke(f, m_pix1.val(), m_pix2.val()); }
reference val() const { return std::invoke(fun_, m_pix1.val(), m_pix2.val()); }
auto point() const { return m_pix1.point(); }
void advance(point_type p)
{
......@@ -186,21 +252,22 @@ namespace mln
}
private:
fun_t f;
fun_t fun_;
image_pixel_t<I1> m_pix1;
image_pixel_t<I2> m_pix2;
};
/// \}
transform2_view() = default;
transform2_view(I1 ima1, I2 ima2, F fun)
: m_ima1{std::move(ima1)}
, m_ima2{std::move(ima2)}
, f{std::move(fun)}
, fun_{std::move(fun)}
{
}
// FIXME: implement copy/move ctors/operators
decltype(auto) concretize() const { return imchvalue<value_type>(this->base()); }
template <class U>
......@@ -211,13 +278,13 @@ namespace mln
auto domain() const { return m_ima1.domain(); }
auto new_values() { return mln::ranges::view::transform(m_ima1.new_values(), m_ima2.new_values(), f); }
auto new_values() { return mln::ranges::view::transform(m_ima1.new_values(), m_ima2.new_values(), fun_); }
auto new_pixels()
{
using R1 = decltype(m_ima1.new_pixels());
using R2 = decltype(m_ima2.new_pixels());
auto pxwrapper = [fun = this->f](::ranges::range_reference_t<R1> px1, ::ranges::range_reference_t<R2> px2) {
auto pxwrapper = [fun = this->fun_](::ranges::range_reference_t<R1> px1, ::ranges::range_reference_t<R2> px2) {
return new_pixel_type{fun, std::move(px1), std::move(px2)};
};
return mln::ranges::view::transform(m_ima1.new_pixels(), m_ima2.new_pixels(), pxwrapper);
......@@ -228,13 +295,13 @@ namespace mln
{
mln_precondition(m_ima1.domain().has(p));
mln_precondition(m_ima2.domain().has(p));
return std::invoke(f, m_ima1.at(p), m_ima2.at(p));
return std::invoke(fun_, m_ima1.at(p), m_ima2.at(p));
}
template <typename dummy = reference>
std::enable_if_t<accessible::value, dummy> at(point_type p)
{
return std::invoke(f, m_ima1.at(p), m_ima2.at(p));
return std::invoke(fun_, m_ima1.at(p), m_ima2.at(p));
}
template <typename dummy = new_pixel_type>
......@@ -242,13 +309,13 @@ namespace mln
{
mln_precondition(m_ima1.domain().has(p));
mln_precondition(m_ima2.domain().has(p));
return {f, m_ima1.new_pixel(p), m_ima2.new_pixel(p)};
return {fun_, m_ima1.new_pixel(p), m_ima2.new_pixel(p)};
}
template <typename dummy = new_pixel_type>
std::enable_if_t<accessible::value, dummy> new_pixel_at(point_type p)
{
return {f, m_ima1.new_pixel_at(p), m_ima2.new_pixel_at(p)};
return {fun_, m_ima1.new_pixel_at(p), m_ima2.new_pixel_at(p)};
}
};
......@@ -256,24 +323,24 @@ namespace mln
namespace view
{
template <class I, class UnaryFunction>
transform_view<I, UnaryFunction> transform(I ima, UnaryFunction f)
transform_view<I, UnaryFunction> transform(I ima, UnaryFunction fun)
{
static_assert(mln::is_a<I, New_Image>());
// FIXME: make ima a view first ?
return {std::move(ima), std::move(f)};
return {std::move(ima), std::move(fun)};
}
template <class I1, class I2, class UnaryFunction>
transform2_view<I1, I2, UnaryFunction> transform(I1 ima1, I2 ima2, UnaryFunction f)
transform2_view<I1, I2, UnaryFunction> transform(I1 ima1, I2 ima2, UnaryFunction fun)
{
static_assert(mln::is_a<I1, New_Image>());
static_assert(mln::is_a<I2, New_Image>());
// FIXME: make ima1 and ima2 a view first ?
return {std::move(ima1), std::move(ima2), std::move(f)};
return {std::move(ima1), std::move(ima2), std::move(fun)};
}
} // namespace view
......
......@@ -41,7 +41,7 @@ TEST(Core, TransformedImage_transform_byval_rvalue)
#ifdef PYLENE_CONCEPT_TS_ENABLED
// bar(std::decay_t<decltype(out)>::new_pixel_type{});
// foo(out);
foo(out);
#endif // PYLENE_CONCEPT_TS_ENABLED
// Test pixel iteration
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment