Commit d59a4ff6 authored by Michaël Roynard's avatar Michaël Roynard
Browse files

WIP: fix adaptors

parent d37bbca5
Pipeline #12292 passed with stages
in 14 minutes and 9 seconds
......@@ -56,7 +56,9 @@
"chrono": "cpp",
"ratio": "cpp",
"system_error": "cpp",
"thread": "cpp"
"thread": "cpp",
"queue": "cpp",
"stack": "cpp"
},
"python.pythonPath": "/usr/bin/python3",
"C_Cpp.configurationWarnings": "Disabled"
......
......@@ -221,15 +221,15 @@ namespace mln::concepts
// Usage: RawImage<I> && OutputImage<I>
template <typename Ima>
concept OutputImage =
(Image<Ima>&& detail::WritableImage<Ima> && not IndexableImage<Ima> && not AccessibleImage<Ima> &&
not BidirectionalImage<Ima> && not RawImage<Ima>) ||
(IndexableImage<Ima> && detail::WritableIndexableImage<Ima> && not AccessibleImage<Ima> &&
not BidirectionalImage<Ima> && not RawImage<Ima>) ||
(AccessibleImage<Ima> && detail::WritableAccessibleImage<Ima> && not IndexableImage<Ima> &&
not BidirectionalImage<Ima> && not RawImage<Ima>) ||
(BidirectionalImage<Ima> && detail::WritableBidirectionalImage<Ima> && not IndexableImage<Ima> &&
not AccessibleImage<Ima> && not RawImage<Ima>) ||
(RawImage<Ima> && detail::WritableRawImage<Ima>);
(not IndexableImage<Ima> && not AccessibleImage<Ima> && not BidirectionalImage<Ima> && not RawImage<Ima> &&
detail::WritableImage<Ima>) ||
(not AccessibleImage<Ima> && not BidirectionalImage<Ima> && not RawImage<Ima> &&
detail::WritableIndexableImage<Ima>) ||
(not IndexableImage<Ima> && not BidirectionalImage<Ima> && not RawImage<Ima> &&
detail::WritableAccessibleImage<Ima>) ||
(not IndexableImage<Ima> && not AccessibleImage<Ima> && not RawImage<Ima> &&
detail::WritableBidirectionalImage<Ima> ) ||
(detail::WritableRawImage<Ima>);
// ExtendedImage
......
#pragma once
#include <mln/core/concept/new/values.hpp>
#include <mln/core/image/image.hpp>
#include <mln/core/image/private/image_traits.hpp>
#include <mln/core/image/private/pixel_traits.hpp>
namespace concepts = mln::concepts;
namespace mln
{
......@@ -10,10 +14,10 @@ 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(); }
......@@ -31,56 +35,85 @@ namespace mln
private:
Pixel m_pix;
/*
public:
template <class LhsPix, class PixRhs>
friend bool operator==(const pixel_adaptor<LhsPix>& lhs, const pixel_adaptor<PixRhs>& rhs)
{
return lhs.base() == rhs.base();
}
template <class Pix>
friend bool operator!=(const pixel_adaptor<Pix>& lhs, const pixel_adaptor<Pix>& rhs)
{
return !(lhs == rhs);
}
*/
};
namespace details
namespace detail
{
template <class I, class = void>
struct image_adaptor_base_indexable
{
};
template <class I>
struct image_adaptor_base_indexable<I, std::enable_if_t<I::indexable::value>>
{
using size_type [[deprecated]] = typename I::size_type;
using difference_type [[deprecated]] = typename I::difference_type;
using size_type[[deprecated]] = image_index_t<I>;
using index_type = size_type;
using difference_type[[deprecated]] = typename I::difference_type;
};
}
template <class I, class = void>
struct image_adaptor_base_extended
{
};
template <class I>
struct image_adaptor_base_extended<
I, std::enable_if_t<not std::is_same_v<image_extension_category_t<I>, mln::extension::none_extension_tag>>>
{
using extension_type = image_extension_t<I>;
};
} // namespace detail
template <class I>
struct image_adaptor : details::image_adaptor_base_indexable<I>
struct image_adaptor : detail::image_adaptor_base_indexable<I>, detail::image_adaptor_base_extended<I>
{
public:
/// Type definitions
/// \{
using reference = typename I::reference;
using value_type = typename I::value_type;
using point_type = typename I::point_type;
using domain_type = typename I::domain_type;
using reference = image_reference_t<I>;
using value_type = image_value_t<I>;
using point_type = image_point_t<I>;
using domain_type = image_domain_t<I>;
using new_pixel_type = pixel_adaptor<image_pixel_t<I>>;
/// \}
/// Traits & Image Properties
/// \{
using accessible = typename I::accessible;
using indexable = typename I::indexable;
using extension_category = typename I::extension_category;
using concrete_type = typename I::concrete_type;
template <class V>
using ch_value_type = typename I::template ch_value_type<V>;
using accessible = image_accessible_t<I>;
using indexable = image_indexable_t<I>;
using extension_category = image_extension_category_t<I>;
using category_type = image_category_t<I>;
using concrete_type = image_concrete_t<I>;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <concepts::Value Val>
#else
template <typename Val>
#endif
using ch_value_type = image_ch_value_t<I, Val>;
/// \}
struct new_pixel_type : pixel_adaptor<typename I::new_pixel_type>
{
using pixel_adaptor<typename I::new_pixel_type>::pixel_adaptor;
};
/////////////////
// Image proxy //
/////////////////
image_adaptor() = default;
image_adaptor(I ima)
......@@ -91,68 +124,112 @@ namespace mln
auto domain() const { return m_ima.domain(); }
auto new_values() { return m_ima.new_values(); }
auto new_pixels() { return m_ima.new_pixels(); }
auto concretize() const { return m_ima.concretize(); }
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <concepts::Value Val>
#else
template <typename Val>
#endif
auto ch_value() const
{
return m_ima.template ch_value<Val>();
}
template <typename dummy = reference>
std::enable_if_t<accessible::value, dummy> operator()(point_type p)
/// Indexable-image related methods
/// \{
template <typename dummy = I>
std::enable_if_t<indexable::value, reference> operator[](image_index_t<dummy> i)
{
return m_ima[i];
}
template <typename dummy = I>
std::enable_if_t<indexable::value, image_index_t<dummy>> index_of_point(point_type p) const
{
return m_ima.index_of_point(p);
}
template <typename dummy = I>
std::enable_if_t<indexable::value, point_type> point_at_index(image_index_t<dummy> i) const
{
return m_ima.point_at_index(i);
}
template <typename dummy = I>
std::enable_if_t<indexable::value, image_index_t<dummy>> delta_index(point_type p) const
{
return m_ima.delta_index(p);
}
/// \}
/// Accessible-image related methods
/// \{
template <typename Ret = reference>
std::enable_if_t<accessible::value, Ret> operator()(point_type p)
{
return m_ima(p);
}
template <typename dummy = reference>
std::enable_if_t<accessible::value, dummy> at(point_type p)
template <typename Ret = reference>
std::enable_if_t<accessible::value, Ret> at(point_type p)
{
return m_ima.at(p);
}
template <typename dummy = new_pixel_type>
std::enable_if_t<accessible::value, dummy> new_pixel(point_type p)
template <typename Ret = new_pixel_type>
std::enable_if_t<accessible::value, Ret> new_pixel(point_type p)
{
return m_ima.new_pixel(p);
}
template <typename dummy = new_pixel_type>
std::enable_if_t<accessible::value, dummy> new_pixel_at(point_type p)
template <typename Ret = new_pixel_type>
std::enable_if_t<accessible::value, Ret> new_pixel_at(point_type p)
{
return m_ima.new_pixel_at(p);
}
/// \}
/// Indexable-image related methods
/// Raw-image related methods
/// \{
template <typename dummy = I>
reference operator[](typename dummy::size_type i)
template <typename Ret = decltype(std::declval<I>().data())>
std::enable_if_t<std::is_base_of_v<raw_image_tag, category_type>, Ret> data() const
{
return m_ima[i];
return m_ima.data();
}
template <typename dummy = I>
std::enable_if_t<indexable::value, typename dummy::size_type> index_of_point(point_type p) const
template <typename Ret = decltype(std::declval<I>().data())>
std::enable_if_t<std::is_base_of_v<raw_image_tag, category_type>, Ret> data()
{
return m_ima.index_of_point(p);
return m_ima.data();
}
template <typename dummy = I>
std::enable_if_t<indexable::value, typename dummy::difference_type> delta_index(point_type p) const
template <typename Ret = std::ptrdiff_t>
std::enable_if_t<std::is_base_of_v<raw_image_tag, category_type>, Ret> strides(int dim) const
{
return m_ima.delta_index(p);
return m_ima.strides(dim);
}
/// \}
/// Extended-image related methods
/// \{
template <typename dummy = I>
reference point_at_index(typename dummy::size_type i) const
std::enable_if_t<not std::is_same_v<extension_category, mln::extension::none_extension_tag>,
image_extension_t<dummy>>
extension() const
{
return m_ima.point_at_index(i);
return m_ima.extension();
}
/// \}
/// \}
protected:
I& base() { return m_ima; }
const I& base() const { return m_ima; }
private:
I m_ima;
};
}
} // namespace mln
......@@ -18,15 +18,15 @@ namespace mln
public:
/// Type definitions
/// \{
using reference = std::invoke_result_t<F&, typename I::reference>;
using value_type = std::decay_t<reference>;
using point_type = typename I::point_type;
using reference = std::invoke_result_t<F&, typename I::reference>;
using value_type = std::decay_t<reference>;
using point_type = typename I::point_type;
static_assert(!(std::is_rvalue_reference_v<reference> && !std::is_reference_v<typename I::reference>),
"The transformed image returns a temporary and the mapping function is a projection.\n"
"This is building a dangling reference.");
using concrete_type = ch_value_t<I, value_type>;
using concrete_type = ch_value_t<I, value_type>;
template <class V>
using ch_value_type = ch_value_t<I, V>;
......@@ -36,8 +36,8 @@ namespace mln
/// Traits & Image Properties
/// \{
using accessible = typename I::accessible;
using indexable = typename I::indexable;
using accessible = typename I::accessible;
using indexable = typename I::indexable;
using extension_category = mln::extension::none_extension_tag; // FIXME: should be improved
/// \}
......@@ -70,8 +70,6 @@ namespace mln
/// \}
transform_view(I ima, F fun)
: transform_view::image_adaptor{std::move(ima)}
, f{std::move(fun)}
......@@ -90,7 +88,7 @@ namespace mln
auto new_pixels()
{
using R = decltype(this->base().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)}; };
return mln::ranges::view::transform(this->base().new_pixels(), pxwrapper);
}
......@@ -126,24 +124,23 @@ namespace mln
{
return std::invoke(f, this->base()[i]);
}
};
template <class I1, class I2, class F>
class transform2_view : public New_Image<transform2_view<I1, I2, F>>
{
using fun_t = F; // FIXME something with semiregular_t<F> ?
I1 m_ima1;
I2 m_ima2;
I1 m_ima1;
I2 m_ima2;
fun_t f;
public:
/// Type definitions
/// \{
using reference = std::invoke_result_t<F&, typename I1::reference, typename I2::reference>;
using value_type = std::decay_t<reference>;
using point_type = typename I1::point_type;
using domain_type = typename I1::domain_type;
using reference = std::invoke_result_t<F&, typename I1::reference, typename I2::reference>;
using value_type = std::decay_t<reference>;
using point_type = typename I1::point_type;
using domain_type = typename I1::domain_type;
/// \}
......@@ -153,7 +150,7 @@ namespace mln
using indexable = std::false_type; // Preservative behavior
using extension_category = mln::extension::none_extension_tag; // Preservative behavior (may be too preservative)
using concrete_type = ch_value_t<I1, value_type>;
using concrete_type = ch_value_t<I1, value_type>;
template <class V>
using ch_value_type = ch_value_t<I1, V>;
......@@ -165,11 +162,10 @@ 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;
......@@ -181,16 +177,16 @@ namespace mln
}
reference val() const { return std::invoke(f, m_pix1.val(), m_pix2.val()); }
auto point() const { return m_pix1.point(); }
void advance(point_type p)
reference val() const { return std::invoke(f, m_pix1.val(), m_pix2.val()); }
auto point() const { return m_pix1.point(); }
void advance(point_type p)
{
m_pix1.advance(p);
m_pix2.advance(p);
}
private:
fun_t f;
fun_t f;
image_pixel_t<I1> m_pix1;
image_pixel_t<I2> m_pix2;
};
......@@ -219,8 +215,8 @@ namespace mln
auto new_pixels()
{
using R1 = decltype(m_ima1.new_pixels());
using R2 = decltype(m_ima2.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) {
return new_pixel_type{fun, std::move(px1), std::move(px2)};
};
......@@ -246,7 +242,7 @@ 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 {f, m_ima1.new_pixel(p), m_ima2.new_pixel(p)};
}
template <typename dummy = new_pixel_type>
......@@ -257,7 +253,6 @@ namespace mln
};
namespace view
{
template <class I, class UnaryFunction>
......@@ -267,7 +262,7 @@ namespace mln
// FIXME: make ima a view first ?
return { std::move(ima), std::move(f) };
return {std::move(ima), std::move(f)};
}
......@@ -277,8 +272,8 @@ namespace mln
static_assert(mln::is_a<I1, New_Image>());
static_assert(mln::is_a<I2, New_Image>());
// FIXME: make ima a view first ?
return { std::move(ima1), std::move(ima2), std::move(f) };
// FIXME: make ima1 and ima2 a view first ?
return {std::move(ima1), std::move(ima2), std::move(f)};
}
} // namespace view
......
......@@ -17,6 +17,7 @@ add_core_test(${test_prefix}range_reverse range/reverse.cpp)
add_core_test(${test_prefix}range_zip range/zip.cpp)
# test Views
add_core_test(${test_prefix}view_adaptor image/view/adaptor.cpp)
add_core_test(${test_prefix}view_transform image/view/transform.cpp)
......
#include <mln/core/concept/new/archetype/pixel.hpp>
#include <mln/core/concept/new/pixels.hpp>
#include <mln/core/image/view/adaptor.hpp>
#include <gtest/gtest.h>
namespace concepts = mln::concepts;
namespace archetypes = mln::archetypes;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <concepts::Pixel Pix>
void foo(Pix)
{
}
#endif // PYLENE_CONCEPT_TS_ENABLED
TEST(Core, ViewAdaptor_Pixel)
{
#ifdef PYLENE_CONCEPT_TS_ENABLED
// foo(mln::pixel_adaptor<archetypes::Pixel>{});
// static_assert(concepts::Pixel<mln::pixel_adaptor<archetypes::Pixel>>);
#endif // PYLENE_CONCEPT_TS_ENABLED
}
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