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

Fix Image concept (not semiregular anymore)

parent 81b24f37
......@@ -13,9 +13,11 @@
namespace mln::archetypes
{
struct Image;
struct Image
struct ConcreteImage;
struct ConcreteImage
{
using new_pixel_type = Pixel;
using value_type = pixel_value_t<Pixel>;
......@@ -23,20 +25,26 @@ namespace mln::archetypes
using point_type = domain_point_t<Domain>;
using domain_type = Domain;
using category_type = forward_image_tag;
using concrete_type = Image;
using concrete_type = ConcreteImage;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <mln::concepts::Value Val>
#else
template <typename Val>
#endif // PYLENE_CONCEPT_TS_ENABLED
using ch_value_type = Image;
using ch_value_type = ConcreteImage;
// additional traits
using extension_category = mln::extension::none_extension_tag;
using indexable = std::false_type;
using accessible = std::false_type;
using view = std::false_type;
ConcreteImage() = default;
ConcreteImage(const ConcreteImage&) = default;
ConcreteImage(ConcreteImage&&) = default;
ConcreteImage& operator=(const ConcreteImage&) = default;
ConcreteImage& operator=(ConcreteImage&&) = default;
#ifdef PYLENE_CONCEPT_TS_ENABLED
template <mln::concepts::Value Val>
......@@ -50,8 +58,8 @@ namespace mln::archetypes
struct PixelRange
{
using value_type = image_pixel_t<Image>;
using reference = image_pixel_t<Image>&;
using value_type = image_pixel_t<ConcreteImage>;
using reference = image_pixel_t<ConcreteImage>&;
new_pixel_type* begin();
new_pixel_type* end();
......@@ -62,16 +70,42 @@ namespace mln::archetypes
struct ValueRange
{
using value_type = image_value_t<Image>;
using reference = image_reference_t<Image>;
using value_type = image_value_t<ConcreteImage>;
using reference = image_reference_t<ConcreteImage>;
image_value_t<Image>* begin();
image_value_t<Image>* end();
image_value_t<ConcreteImage>* begin();
image_value_t<ConcreteImage>* end();
};
ValueRange new_values();
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::ConcreteImage<ConcreteImage>,
"ConcreteImage archetype does not model the ConcreteImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct ViewImage : ConcreteImage
{
using view = std::true_type;
ViewImage() = delete;
ViewImage(const ViewImage&) = delete;
ViewImage(ViewImage&&) = default;
ViewImage& operator=(const ViewImage&) = delete;
ViewImage& operator=(ViewImage&&) = default;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::ViewImage<ViewImage>, "ViewImage archetype does not model the ViewImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct Image : ViewImage
{
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::Image<Image>, "Image archetype does not model the Image concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......@@ -136,9 +170,6 @@ namespace mln::archetypes
using indexable = std::true_type;
image_reference_t<IndexableImage> operator[](image_index_t<IndexableImage>) const;
image_point_t<IndexableImage> point_at_index(image_index_t<IndexableImage>) const;
image_index_t<IndexableImage> index_of_point(image_point_t<IndexableImage>) const;
image_index_t<IndexableImage> delta_index(image_point_t<IndexableImage>) const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
......@@ -191,7 +222,7 @@ namespace mln::archetypes
#endif // PYLENE_CONCEPT_TS_ENABLED
struct OutputAccessibleImage final : AccessibleImage
struct OutputAccessibleImage : AccessibleImage
{
using new_pixel_type = OutputPixel;
using reference = pixel_reference_t<OutputPixel>;
......@@ -218,13 +249,54 @@ namespace mln::archetypes
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::AccessibleImage<OutputAccessibleImage> &&
mln::concepts::OutputImage<OutputAccessibleImage>,
"OutputAccessibleImage archetype does not model the OutputImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct IndexableAndAccessibleImage : AccessibleImage
{
using index_type = int;
using indexable = std::true_type;
image_reference_t<IndexableAndAccessibleImage> operator[](image_index_t<IndexableAndAccessibleImage>) const;
image_point_t<IndexableAndAccessibleImage> point_at_index(image_index_t<IndexableAndAccessibleImage>) const;
image_index_t<IndexableAndAccessibleImage> index_of_point(image_point_t<IndexableAndAccessibleImage>) const;
image_index_t<IndexableAndAccessibleImage> delta_index(image_point_t<IndexableAndAccessibleImage>) const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::IndexableAndAccessibleImage<IndexableAndAccessibleImage>,
"IndexableAndAccessibleImage archetype does not model the IndexableAndAccessibleImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct OutputIndexableAndAccessibleImage : OutputAccessibleImage
{
using index_type = int;
using indexable = std::true_type;
image_reference_t<OutputIndexableAndAccessibleImage>
operator[](image_index_t<OutputIndexableAndAccessibleImage>) const;
image_reference_t<OutputIndexableAndAccessibleImage> operator[](image_index_t<OutputIndexableAndAccessibleImage>);
image_point_t<OutputIndexableAndAccessibleImage>
point_at_index(image_index_t<OutputIndexableAndAccessibleImage>) const;
image_index_t<OutputIndexableAndAccessibleImage>
index_of_point(image_point_t<OutputIndexableAndAccessibleImage>) const;
image_index_t<OutputIndexableAndAccessibleImage>
delta_index(image_point_t<OutputIndexableAndAccessibleImage>) const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::IndexableAndAccessibleImage<OutputIndexableAndAccessibleImage> &&
mln::concepts::OutputImage<OutputIndexableAndAccessibleImage>,
"OutputIndexableAndAccessibleImage archetype does not model the OutputImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
struct BidirectionalImage : Image
{
using category_type = bidirectional_image_tag;
......@@ -245,7 +317,6 @@ namespace mln::archetypes
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::BidirectionalImage<BidirectionalImage>,
"BidirectionalImage archetype does not model the BidirectionalImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......@@ -280,22 +351,9 @@ namespace mln::archetypes
#endif // PYLENE_CONCEPT_TS_ENABLED
struct RawImage : Image
struct RawImage : IndexableAndAccessibleImage
{
using category_type = raw_image_tag;
using index_type = int;
using indexable = std::true_type;
using accessible = std::true_type;
image_reference_t<RawImage> operator[](image_index_t<RawImage>) const;
image_point_t<RawImage> point_at_index(image_index_t<RawImage>) const;
image_index_t<RawImage> index_of_point(image_point_t<RawImage>) const;
image_index_t<RawImage> delta_index(image_point_t<RawImage>) const;
image_reference_t<RawImage> operator()(image_point_t<RawImage>) const;
image_reference_t<RawImage> at(image_point_t<RawImage>) const;
image_pixel_t<RawImage> new_pixel(image_point_t<RawImage>) const;
image_pixel_t<RawImage> new_pixel_at(image_point_t<RawImage>) const;
struct ReversiblePixelRange final : Image::PixelRange
......@@ -318,7 +376,6 @@ namespace mln::archetypes
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::RawImage<RawImage>, "RawImage archetype does not model the RawImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
......@@ -369,7 +426,7 @@ namespace mln::archetypes
#endif // PYLENE_CONCEPT_TS_ENABLED
struct ExtendedImage : Image
struct WithExtensionImage : Image
{
struct Extension
{
......@@ -379,11 +436,12 @@ namespace mln::archetypes
using extension_category = mln::extension::custom_extension_tag;
image_extension_t<ExtendedImage> extension() const;
image_extension_t<WithExtensionImage> extension() const;
};
#ifdef PYLENE_CONCEPT_TS_ENABLED
static_assert(mln::concepts::ExtendedImage<ExtendedImage>,
"ExtendedImage archetype does not model the ExtendedImage concept!");
static_assert(mln::concepts::WithExtensionImage<WithExtensionImage>,
"WithExtensionImage archetype does not model the WithExtensionImage concept!");
#endif // PYLENE_CONCEPT_TS_ENABLED
} // namespace mln::archetypes
......@@ -24,15 +24,15 @@
namespace mln::concepts
{
// clang-format off
// clang-format off
#ifdef PYLENE_CONCEPT_TS_ENABLED
// Image
template<typename Ima>
concept Image =
// FIXME : inheritance from New_Image required for the moment
stl::Semiregular<Ima> &&
// FIXME: inheritance from New_Image required for the moment
stl::Movable<Ima> && // Minimum constraint on image object
stl::DerivedFrom<image_category_t<Ima>, forward_image_tag> &&
requires {
typename image_pixel_t<Ima>;
......@@ -47,6 +47,7 @@ namespace mln::concepts
typename image_accessible_t<Ima>;
typename image_extension_category_t<Ima>;
typename image_category_t<Ima>;
typename image_view_t<Ima>;
} &&
Pixel<image_pixel_t<Ima>> &&
Point<image_point_t<Ima>> &&
......@@ -110,11 +111,8 @@ namespace mln::concepts
typename image_index_t<Ima>;
} &&
image_indexable_v<Ima> &&
requires (Ima ima, const Ima cima, image_index_t<Ima> k, image_point_t<Ima> p) {
{ ima[k] } -> image_reference_t<Ima>; // For concrete image it returns a const_reference
{ cima.point_at_index(k) } -> image_point_t<Ima>;
{ cima.index_of_point(p) } -> image_index_t<Ima>;
{ cima.delta_index(p) } -> image_index_t<Ima>;
requires (Ima ima, image_index_t<Ima> k) {
{ ima[k] } -> image_reference_t<Ima>; // For concrete image it returns a const_reference
};
......@@ -162,6 +160,31 @@ namespace mln::concepts
} // namespace detail
// IndexableAndAccessibleImage
template <typename Ima>
concept IndexableAndAccessibleImage =
IndexableImage<Ima> &&
AccessibleImage<Ima> &&
requires (const Ima cima, image_index_t<Ima> k, image_point_t<Ima> p) {
{ cima.point_at_index(k) } -> image_point_t<Ima>;
{ cima.index_of_point(p) } -> image_index_t<Ima>;
{ cima.delta_index(p) } -> image_index_t<Ima>;
};
namespace detail
{
// WritableIndexableAndAccessibleImage
template<typename WIma>
concept WritableIndexableAndAccessibleImage =
IndexableAndAccessibleImage<WIma> &&
detail::WritableImage<WIma> &&
detail::WritableIndexableImage<WIma>;
} // namespace detail
// BidirectionalImage (not in STL term)
template <typename Ima>
concept BidirectionalImage =
......@@ -188,8 +211,7 @@ namespace mln::concepts
// RawImage (not contiguous, stride = padding)
template <typename Ima>
concept RawImage =
IndexableImage<Ima> &&
AccessibleImage<Ima> &&
IndexableAndAccessibleImage<Ima> &&
BidirectionalImage<Ima> &&
stl::DerivedFrom<image_category_t<Ima>, raw_image_tag> &&
requires (Ima ima, const Ima cima, int dim) {
......@@ -205,8 +227,7 @@ namespace mln::concepts
template<typename WIma>
concept WritableRawImage =
WritableImage<WIma> &&
WritableIndexableImage<WIma> &&
WritableAccessibleImage<WIma> &&
WritableIndexableAndAccessibleImage<WIma> &&
WritableBidirectionalImage<WIma> &&
RawImage<WIma> &&
requires(WIma ima, image_value_t<WIma> v) {
......@@ -221,20 +242,18 @@ namespace mln::concepts
// Usage: RawImage<I> && OutputImage<I>
template <typename Ima>
concept OutputImage =
(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
(not ForwardImage<Ima> || (ForwardImage<Ima> && detail::WritableImage<Ima>)) &&
(not IndexableImage<Ima> || (IndexableImage<Ima> && detail::WritableIndexableImage<Ima>)) &&
(not AccessibleImage<Ima> || (AccessibleImage<Ima> && detail::WritableAccessibleImage<Ima>)) &&
(not IndexableAndAccessibleImage<Ima> ||
(IndexableAndAccessibleImage<Ima> && detail::WritableIndexableAndAccessibleImage<Ima>)) &&
(not BidirectionalImage<Ima> || (BidirectionalImage<Ima> && detail::WritableBidirectionalImage<Ima>)) &&
(not RawImage<Ima> || (RawImage<Ima> && detail::WritableRawImage<Ima>));
// WithExtensionImage
template <typename Ima>
concept ExtendedImage =
concept WithExtensionImage =
Image<Ima> &&
requires {
typename image_extension_t<Ima>;
......@@ -245,7 +264,19 @@ namespace mln::concepts
};
// TODO: think about ViewImage vs. ConcreteImage
// ConcreteImage
template <typename Ima>
concept ConcreteImage =
Image<Ima> &&
stl::Semiregular<Ima> && // A concrete image is default constructible
not image_view_v<Ima>;
// ViewImage
template <typename Ima>
concept ViewImage =
Image<Ima> &&
image_view_v<Ima>;
#endif // PYLENE_CONCEPT_TS_ENABLED
......
......@@ -141,6 +141,7 @@ namespace mln
using accessible = std::true_type;
using indexable = std::true_type;
using concrete[[deprecated]] = std::true_type;
using view = std::false_type;
using shallow_copy[[deprecated]] = std::true_type;
using has_border[[deprecated]] = std::true_type;
using extension_category = mln::extension::border_extension_tag;
......
......@@ -54,4 +54,9 @@ namespace mln
template <class I>
using image_category_t = typename I::category_type;
// View trait
template <class I>
using image_view_t = typename I::view;
template <class I>
inline constexpr auto image_view_v = image_view_t<I>::value;
} // namespace mln
......@@ -77,18 +77,17 @@ 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 difference_type[[deprecated]] = typename I::difference_type;
using size_type[[deprecated]] = image_index_t<I>;
using index_type = size_type;
};
template <class I, class = void>
struct image_adaptor_base_extended
struct image_adaptor_base_with_extension
{
};
template <class I>
struct image_adaptor_base_extended<
struct image_adaptor_base_with_extension<
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>;
......@@ -97,7 +96,7 @@ namespace mln
template <class I>
struct image_adaptor : detail::image_adaptor_base_indexable<I>, detail::image_adaptor_base_extended<I>
struct image_adaptor : detail::image_adaptor_base_indexable<I>, detail::image_adaptor_base_with_extension<I>
{
public:
/// Type definitions
......@@ -113,6 +112,7 @@ namespace mln
/// \{
using accessible = image_accessible_t<I>;
using indexable = image_indexable_t<I>;
using view = std::true_type;
using extension_category = image_extension_category_t<I>;
using category_type = image_category_t<I>;
using concrete_type = image_concrete_t<I>;
......@@ -130,7 +130,6 @@ namespace mln
// Image proxy //
/////////////////
image_adaptor() = default;
image_adaptor(I ima)
: m_ima(std::move(ima))
{
......@@ -154,28 +153,10 @@ namespace mln
/// Indexable-image related methods
/// \{
template <typename dummy = I, typename Ret = reference>
std::enable_if_t<indexable::value, Ret> 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
reference operator[](image_index_t<dummy> i)
{
return m_ima.index_of_point(p);
}
template <typename dummy = I, typename Ret = point_type>
std::enable_if_t<indexable::value, Ret> 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);
return m_ima[i];
}
/// \}
......@@ -207,17 +188,39 @@ namespace mln
}
/// \}
/// IndexableAndAccessible-image related methods
/// \{
template <typename dummy = I>
std::enable_if_t<(indexable::value && accessible::value), image_index_t<dummy>> index_of_point(point_type p) const
{
return m_ima.index_of_point(p);
}
template <typename dummy = I, typename = std::enable_if_t<(indexable::value && accessible::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 && accessible::value), image_index_t<dummy>> delta_index(point_type p) const
{
return m_ima.delta_index(p);
}
/// \}
/// Raw-image related methods
/// \{
template <typename dummy = I>
std::enable_if_t<std::is_base_of_v<raw_image_tag, category_type>, decltype(std::declval<dummy>().data())>
data() const
decltype(std::declval<dummy>().data()) data() const
{
return m_ima.data();
}
template <typename dummy = I>
std::enable_if_t<std::is_base_of_v<raw_image_tag, category_type>, decltype(std::declval<dummy>().data())> data()
decltype(std::declval<dummy>().data()) data()
{
return m_ima.data();
}
......@@ -229,7 +232,8 @@ namespace mln
}
/// \}
/// Extended-image related methods
/// WithExtension-image related methods
/// \{
template <typename dummy = I>
std::enable_if_t<not std::is_same_v<extension_category, mln::extension::none_extension_tag>,
......
......@@ -17,8 +17,11 @@ TEST(Core, Concept_Image)
static_assert(concepts::Image<archetypes::InputImage>);
static_assert(concepts::Image<archetypes::IndexableImage>);
static_assert(concepts::Image<archetypes::AccessibleImage>);
static_assert(concepts::Image<archetypes::IndexableAndAccessibleImage>);
static_assert(concepts::Image<archetypes::BidirectionalImage>);
static_assert(concepts::Image<archetypes::RawImage>);
static_assert(concepts::Image<archetypes::ConcreteImage>);
static_assert(concepts::Image<archetypes::ViewImage>);
}
TEST(Core, Concept_ForwardImage)
......@@ -28,8 +31,11 @@ TEST(Core, Concept_ForwardImage)
static_assert(concepts::ForwardImage<archetypes::InputImage>);
static_assert(concepts::ForwardImage<archetypes::IndexableImage>);
static_assert(concepts::ForwardImage<archetypes::AccessibleImage>);
static_assert(concepts::ForwardImage<archetypes::IndexableAndAccessibleImage>);
static_assert(concepts::ForwardImage<archetypes::BidirectionalImage>);
static_assert(concepts::ForwardImage<archetypes::RawImage>);
static_assert(concepts::ForwardImage<archetypes::ConcreteImage>);
static_assert(concepts::ForwardImage<archetypes::ViewImage>);
}
TEST(Core, Concept_InputImage)
......@@ -39,8 +45,11 @@ TEST(Core, Concept_InputImage)
static_assert(concepts::InputImage<archetypes::InputImage>);
static_assert(concepts::InputImage<archetypes::IndexableImage>);
static_assert(concepts::InputImage<archetypes::AccessibleImage>);
static_assert(concepts::InputImage<archetypes::IndexableAndAccessibleImage>);
static_assert(concepts::InputImage<archetypes::BidirectionalImage>);
static_assert(concepts::InputImage<archetypes::RawImage>);
static_assert(concepts::InputImage<archetypes::ConcreteImage>);
static_assert(concepts::InputImage<archetypes::ViewImage>);
}
TEST(Core, Concept_IndexableImage)
......@@ -50,6 +59,7 @@ TEST(Core, Concept_IndexableImage)
static_assert(not concepts::IndexableImage<archetypes::InputImage>);
static_assert(concepts::IndexableImage<archetypes::IndexableImage>);
static_assert(not concepts::IndexableImage<archetypes::AccessibleImage>);
static_assert(concepts::IndexableImage<archetypes::IndexableAndAccessibleImage>);
static_assert(not concepts::IndexableImage<archetypes::BidirectionalImage>);
static_assert(concepts::IndexableImage<archetypes::RawImage>);
}
......@@ -61,10 +71,23 @@ TEST(Core, Concept_AccessibleImage)
static_assert(not concepts::AccessibleImage<archetypes::InputImage>);
static_assert(not concepts::AccessibleImage<archetypes::IndexableImage>);
static_assert(concepts::AccessibleImage<archetypes::AccessibleImage>);
static_assert(concepts::AccessibleImage<archetypes::IndexableAndAccessibleImage>);
static_assert(not concepts::AccessibleImage<archetypes::BidirectionalImage>);
static_assert(concepts::AccessibleImage<archetypes::RawImage>);
}
TEST(Core, Concept_IndexableAndAccessibleImage)
{
static_assert(not concepts::IndexableAndAccessibleImage<archetypes::Image>);
static_assert(not concepts::IndexableAndAccessibleImage<archetypes::ForwardImage>);
static_assert(not concepts::IndexableAndAccessibleImage<archetypes::InputImage>);
static_assert(not concepts::IndexableAndAccessibleImage<archetypes::IndexableImage>);
static_assert(not concepts::IndexableAndAccessibleImage<archetypes::AccessibleImage>);
static_assert(concepts::IndexableAndAccessibleImage<archetypes::IndexableAndAccessibleImage>);
static_assert(not concepts::IndexableAndAccessibleImage<archetypes::BidirectionalImage>);
static_assert(concepts::IndexableAndAccessibleImage<archetypes::RawImage>);
}
TEST(Core, Concept_BidirectionalImage)
{
static_assert(not concepts::BidirectionalImage<archetypes::Image>);
......@@ -72,6 +95,7 @@ TEST(Core, Concept_BidirectionalImage)
static_assert(not concepts::BidirectionalImage<archetypes::InputImage>