From c8419f18a740699cbd57c8979436c80041b046d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Thu, 7 Mar 2019 17:32:17 +0100 Subject: [PATCH 01/61] WIP --- conanfile.py | 4 ++-- pylene/CMakeLists.txt | 1 - .../include/mln/core/concept/new/cmcstl2.hpp | 22 ++----------------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/conanfile.py b/conanfile.py index 04c9b87c..585eea48 100644 --- a/conanfile.py +++ b/conanfile.py @@ -39,8 +39,8 @@ class Pylene(ConanFile): # Requirements part of the INTERFACE def requirements(self): - self.requires("range-v3/0.4.0@ericniebler/stable") - self.requires("cmcstl2/0.1@dutiona/testing") + self.requires("range-v3/head@dutiona/testing") + self.requires("cmcstl2/head@dutiona/testing") if self.options.freeimage: self.requires("freeimage/3.18.0@dutiona/stable") diff --git a/pylene/CMakeLists.txt b/pylene/CMakeLists.txt index 18ebab97..05d93c47 100644 --- a/pylene/CMakeLists.txt +++ b/pylene/CMakeLists.txt @@ -57,7 +57,6 @@ if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.2) find_package(cmcstl2 REQUIRED) target_link_libraries(Pylene PUBLIC stl2) target_compile_definitions(Pylene PUBLIC PYLENE_CONCEPT_TS_ENABLED) - target_compile_definitions(Pylene PUBLIC concept="concept bool") endif() diff --git a/pylene/include/mln/core/concept/new/cmcstl2.hpp b/pylene/include/mln/core/concept/new/cmcstl2.hpp index 3beac1d7..b910a956 100644 --- a/pylene/include/mln/core/concept/new/cmcstl2.hpp +++ b/pylene/include/mln/core/concept/new/cmcstl2.hpp @@ -1,34 +1,14 @@ #pragma once -/* DO NOT REMOVE */ - -// stl2/meta and ranges-v3/meta are not the same but have the same header guard (><)!!. -// stl2 works with ranges-v3/meta, but ranges-v3 doesn't work with stl2/meta -// here we force the usage of ranges-v3/meta -// stl2/meta is in -#include - - #ifdef PYLENE_CONCEPT_TS_ENABLED -#ifdef concept -#define __concept_bool -#undef concept -#endif - #include -#ifdef __concept_bool -#define concept concept bool -#undef __concept_bool -#endif - namespace mln::concepts::stl { using namespace __stl2; } - // Dirty hack to allow proper conversion from ranges iterator iterator tags to __stl2 iterator tags #include @@ -80,4 +60,6 @@ namespace std::experimental::ranges } // namespace v1 } // namespace std::experimental::ranges +#define concept META_CONCEPT + #endif // PYLENE_CONCEPT_TS_ENABLED -- GitLab From 965224887eef20bd5458bf7b1693225337cfa523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 8 Mar 2019 17:47:17 +0100 Subject: [PATCH 02/61] Fix compile error for mln::ranges::view --- pylene/include/mln/core/rangev3/view/filter.hpp | 17 +++++++++++++---- .../include/mln/core/rangev3/view/remove_if.hpp | 15 ++++++++++++--- pylene/src/core/se/disc.cpp | 2 +- tests/core/range/transform.cpp | 3 +-- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/pylene/include/mln/core/rangev3/view/filter.hpp b/pylene/include/mln/core/rangev3/view/filter.hpp index a4203e00..14c19cd9 100644 --- a/pylene/include/mln/core/rangev3/view/filter.hpp +++ b/pylene/include/mln/core/rangev3/view/filter.hpp @@ -15,8 +15,12 @@ namespace mln::ranges::view struct filter_fn { template - using Constraint = - ::meta::and_<::ranges::InputRange, ::ranges::IndirectPredicate>>; + using Constraint = ::meta::and_<::ranges::InputRange, ::ranges::CopyConstructible, + ::ranges::Predicate>> + // FIXME: IndirectPredicate is bugged, see issue #1077 + // https://github.com/ericniebler/range-v3/issues/1077 + //, ::ranges::IndirectPredicate> + >; template ())> // clang-format off @@ -24,7 +28,7 @@ namespace mln::ranges::view requires mln::concepts::stl::InputRange && mln::concepts::stl::IndirectUnaryPredicate> #endif - remove_if_view<::ranges::view::all_t, ::ranges::logical_negate> operator()(Rng&& rng, Pred pred) const + remove_if_view<::ranges::view::all_t, ::ranges::logical_negate> operator()(Rng&& rng, Pred pred) const // clang-format on { return {::ranges::view::all(static_cast(rng)), ::ranges::not_fn(std::move(pred))}; @@ -35,7 +39,12 @@ namespace mln::ranges::view { CONCEPT_ASSERT_MSG(::ranges::InputRange(), "The first argument to view::remove_if must be a model of the " "InputRange concept"); - CONCEPT_ASSERT_MSG(::ranges::IndirectPredicate>(), + CONCEPT_ASSERT_MSG(::meta::and_<::ranges::CopyConstructible, + ::ranges::Predicate>> + // FIXME: IndirectPredicate is bugged, see issue #1077 + // https://github.com/ericniebler/range-v3/issues/1077 + //::ranges::IndirectPredicate + >(), "The second argument to view::remove_if must be callable with " "a value of the range, and the return type must be convertible " "to bool"); diff --git a/pylene/include/mln/core/rangev3/view/remove_if.hpp b/pylene/include/mln/core/rangev3/view/remove_if.hpp index 803d9ca9..4be0fe98 100644 --- a/pylene/include/mln/core/rangev3/view/remove_if.hpp +++ b/pylene/include/mln/core/rangev3/view/remove_if.hpp @@ -84,8 +84,12 @@ namespace mln::ranges public: template - using Constraint = - ::meta::and_<::ranges::InputRange, ::ranges::IndirectPredicate>>; + using Constraint = ::meta::and_<::ranges::InputRange, + ::ranges::Predicate>> + // FIXME: IndirectPredicate is bugged, see issue #1077 + // https://github.com/ericniebler/range-v3/issues/1077 + // ::ranges::IndirectPredicate> + >; template ())> #ifdef PYLENE_CONCEPT_TS_ENABLED @@ -103,7 +107,12 @@ namespace mln::ranges { CONCEPT_ASSERT_MSG(::ranges::InputRange(), "The first argument to view::remove_if must be a model of the " "InputRange concept"); - CONCEPT_ASSERT_MSG(::ranges::IndirectPredicate>(), + CONCEPT_ASSERT_MSG(::meta::and_<::ranges::CopyConstructible, + ::ranges::Predicate>> + // FIXME: IndirectPredicate is bugged, see issue #1077 + // https://github.com/ericniebler/range-v3/issues/1077 + //::ranges::IndirectPredicate + >(), "The second argument to view::remove_if must be callable with " "a value of the range, and the return type must be convertible " "to bool"); diff --git a/pylene/src/core/se/disc.cpp b/pylene/src/core/se/disc.cpp index fd26998c..205246f3 100644 --- a/pylene/src/core/se/disc.cpp +++ b/pylene/src/core/se/disc.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include diff --git a/tests/core/range/transform.cpp b/tests/core/range/transform.cpp index 58b94a39..3107d1ae 100644 --- a/tests/core/range/transform.cpp +++ b/tests/core/range/transform.cpp @@ -1,10 +1,9 @@ +#include #include #include #include #include -#include - #include #include -- GitLab From be3488120805f7f1ae12b5eba24dbae7f0066b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 8 Mar 2019 17:56:34 +0100 Subject: [PATCH 03/61] WIP : temporary fix algorithms --- pylene/include/mln/core/algorithm/all_of.hpp | 11 +++++++++-- pylene/include/mln/core/algorithm/any_of.hpp | 11 +++++++++-- pylene/include/mln/core/algorithm/clone.hpp | 6 ++++++ pylene/include/mln/core/algorithm/count.hpp | 9 +++++++-- pylene/include/mln/core/algorithm/count_if.hpp | 7 ++++++- pylene/include/mln/core/algorithm/equal.hpp | 8 ++++++-- pylene/include/mln/core/algorithm/for_each.hpp | 6 +++++- pylene/include/mln/core/algorithm/none_of.hpp | 12 ++++++++++-- pylene/include/mln/core/algorithm/transform.hpp | 6 +++++- pylene/include/mln/core/image/image_routines.hpp | 10 +++++++++- tests/core/algorithm/copy.cpp | 4 +--- tests/core/algorithm/paste.cpp | 13 +++++++++---- tests/core/image/view/zip.cpp | 10 ++++++++-- tests/core/image/zip_image.cpp | 11 +++++++++-- 14 files changed, 99 insertions(+), 25 deletions(-) diff --git a/pylene/include/mln/core/algorithm/all_of.hpp b/pylene/include/mln/core/algorithm/all_of.hpp index 141157e3..a471ce57 100644 --- a/pylene/include/mln/core/algorithm/all_of.hpp +++ b/pylene/include/mln/core/algorithm/all_of.hpp @@ -2,9 +2,11 @@ #include #include + #include #include + namespace mln { template @@ -24,9 +26,14 @@ namespace mln static_assert(::ranges::Predicate>()); auto&& vals = input.new_values(); + // FIXME: + // for (auto r : ranges::rows(vals)) + // if (!::ranges::all_of(r, p)) + // return false; for (auto r : ranges::rows(vals)) - if (!::ranges::all_of(r, p)) - return false; + for (auto&& v : r) + if (not std::invoke(p, v)) + return false; return true; } diff --git a/pylene/include/mln/core/algorithm/any_of.hpp b/pylene/include/mln/core/algorithm/any_of.hpp index 370345e1..07c88b67 100644 --- a/pylene/include/mln/core/algorithm/any_of.hpp +++ b/pylene/include/mln/core/algorithm/any_of.hpp @@ -2,9 +2,11 @@ #include #include + #include #include + namespace mln { template @@ -24,9 +26,14 @@ namespace mln static_assert(::ranges::Predicate>()); auto&& vals = input.new_values(); + // FIXME: + // for (auto r : ranges::rows(vals)) + // if (::ranges::any_of(r, p)) + // return true; for (auto r : ranges::rows(vals)) - if (::ranges::any_of(r, p)) - return true; + for (auto&& v : r) + if (std::invoke(p, v)) + return true; return false; } diff --git a/pylene/include/mln/core/algorithm/clone.hpp b/pylene/include/mln/core/algorithm/clone.hpp index 108f05ce..1d824d8f 100644 --- a/pylene/include/mln/core/algorithm/clone.hpp +++ b/pylene/include/mln/core/algorithm/clone.hpp @@ -8,6 +8,12 @@ namespace mln { + // FIXME: to remove once circular dependency between image/clone/copy is resolved + namespace experimental + { + template + void copy(InputImage src, OutputImage dest); + } // namespace experimental /// \ingroup Algorithms /// \brief Make and return a deep copy of an image. diff --git a/pylene/include/mln/core/algorithm/count.hpp b/pylene/include/mln/core/algorithm/count.hpp index bbc0f3c7..be663dee 100644 --- a/pylene/include/mln/core/algorithm/count.hpp +++ b/pylene/include/mln/core/algorithm/count.hpp @@ -19,15 +19,20 @@ namespace mln /******************/ template - std::ptrdiff_t count(InputImage input, const Value& v) + std::ptrdiff_t count(InputImage input, const Value& val) { static_assert(mln::is_a()); auto&& vals = input.new_values(); std::ptrdiff_t k = 0; + // FIXME: + // for (auto r : ranges::rows(vals)) + // k += ::ranges::count(r, v); for (auto r : ranges::rows(vals)) - k += ::ranges::count(r, v); + for (auto&& v : r) + if (v == val) + ++k; return k; } diff --git a/pylene/include/mln/core/algorithm/count_if.hpp b/pylene/include/mln/core/algorithm/count_if.hpp index decb2c5a..c2feff3a 100644 --- a/pylene/include/mln/core/algorithm/count_if.hpp +++ b/pylene/include/mln/core/algorithm/count_if.hpp @@ -25,8 +25,13 @@ namespace mln auto&& vals = input.new_values(); std::ptrdiff_t k = 0; + // FIXME: + // for (auto r : ranges::rows(vals)) + // k += ::ranges::count_if(r, std::move(p)); for (auto r : ranges::rows(vals)) - k += ::ranges::count_if(r, std::move(p)); + for (auto&& v : r) + if (std::invoke(p, v)) + ++k; return k; } diff --git a/pylene/include/mln/core/algorithm/equal.hpp b/pylene/include/mln/core/algorithm/equal.hpp index e888d4d3..3ca3d6ca 100644 --- a/pylene/include/mln/core/algorithm/equal.hpp +++ b/pylene/include/mln/core/algorithm/equal.hpp @@ -41,8 +41,12 @@ namespace mln for (auto [lhs_r, rhs_r] : ranges::view::zip(ranges::rows(lhs_vals), ranges::rows(rhs_vals))) // FIXME: with std::equal you gain performances over ranges::equal here - if (!::ranges::equal(lhs_r, rhs_r)) - return false; + // FIXME: + // if (!::ranges::equal(lhs_r, rhs_r)) + // return false; + for (auto [lhs_v, rhs_v] : ranges::view::zip(lhs_r, rhs_r)) + if (not(lhs_v == rhs_v)) + return false; return true; } diff --git a/pylene/include/mln/core/algorithm/for_each.hpp b/pylene/include/mln/core/algorithm/for_each.hpp index 2e925e77..30d84c4e 100644 --- a/pylene/include/mln/core/algorithm/for_each.hpp +++ b/pylene/include/mln/core/algorithm/for_each.hpp @@ -21,8 +21,12 @@ namespace mln static_assert(::ranges::Invocable>()); auto&& vals = input.new_values(); + // FIXME: + // for (auto r : ranges::rows(vals)) + // ::ranges::for_each(r, f); for (auto r : ranges::rows(vals)) - ::ranges::for_each(r, f); + for (auto&& e : r) + std::invoke(f, e); } } // namespace mln diff --git a/pylene/include/mln/core/algorithm/none_of.hpp b/pylene/include/mln/core/algorithm/none_of.hpp index 0cf1c9a3..41183ba9 100644 --- a/pylene/include/mln/core/algorithm/none_of.hpp +++ b/pylene/include/mln/core/algorithm/none_of.hpp @@ -2,9 +2,11 @@ #include #include + #include #include + namespace mln { @@ -25,9 +27,15 @@ namespace mln static_assert(::ranges::Predicate>()); auto&& vals = input.new_values(); + // FIXME: + // for (auto r : ranges::rows(vals)) + // if (!::ranges::none_of(r, p)) + // return false; + for (auto r : ranges::rows(vals)) - if (!::ranges::none_of(r, p)) - return false; + for (auto&& v : r) + if (std::invoke(p, v)) + return false; return true; } diff --git a/pylene/include/mln/core/algorithm/transform.hpp b/pylene/include/mln/core/algorithm/transform.hpp index e32505df..bd3f111f 100644 --- a/pylene/include/mln/core/algorithm/transform.hpp +++ b/pylene/include/mln/core/algorithm/transform.hpp @@ -57,8 +57,12 @@ namespace mln auto&& ivals = in.new_values(); auto&& ovals = out.new_values(); + // FIXME: + // for (auto [r1, r2] : ranges::view::zip(ranges::rows(ivals), ranges::rows(ovals))) + // ::ranges::transform(r1, ::ranges::begin(r2), f); for (auto [r1, r2] : ranges::view::zip(ranges::rows(ivals), ranges::rows(ovals))) - ::ranges::transform(r1, ::ranges::begin(r2), f); + for (auto&& [v1, v2] : ranges::view::zip(r1, r2)) + v2 = std::invoke(f, v1); } template diff --git a/pylene/include/mln/core/image/image_routines.hpp b/pylene/include/mln/core/image/image_routines.hpp index f003f0e9..26630280 100644 --- a/pylene/include/mln/core/image/image_routines.hpp +++ b/pylene/include/mln/core/image/image_routines.hpp @@ -13,6 +13,15 @@ #include +namespace mln +{ + // FIXME: to remove once circular dependency between image/clone/copy is resolved + template + [[deprecated]] OutputImage& copy(const Image& input, Image& output); + template + [[deprecated]] OutputImage&& copy(const Image& input, Image&& output); +} // namespace mln + // FIXME: namespace to_migrate { @@ -48,7 +57,6 @@ namespace to_migrate namespace mln { - /// \defgroup free_functions Free functions /// \ingroup image /// \{ diff --git a/tests/core/algorithm/copy.cpp b/tests/core/algorithm/copy.cpp index c5717d99..0f457e3f 100644 --- a/tests/core/algorithm/copy.cpp +++ b/tests/core/algorithm/copy.cpp @@ -1,8 +1,7 @@ -#include - #include #include #include +#include #include @@ -28,4 +27,3 @@ TEST(Core, Algorithm_Exp_Copy) ASSERT_TRUE(mln::equal(ima, out)); } - diff --git a/tests/core/algorithm/paste.cpp b/tests/core/algorithm/paste.cpp index c1ab399a..bfaea523 100644 --- a/tests/core/algorithm/paste.cpp +++ b/tests/core/algorithm/paste.cpp @@ -1,10 +1,10 @@ -#include -#include - #include #include #include +#include +#include #include + #include #include @@ -41,7 +41,12 @@ TEST(Core, Experimental_Algorithm_Paste) // 16 x x 19 // 31 x x 34 // 46 47 48 49 - int r = ::ranges::accumulate(out.new_values(), 0); + + // FIXME: + // int r = ::ranges::accumulate(out.new_values(), 0); + int r = 0; + for (auto&& v : out.new_values()) + r += v; ASSERT_EQ(r, 225 * 226 / 2 - (17 + 18 + 32 + 33) + 69 * 4); } diff --git a/tests/core/image/view/zip.cpp b/tests/core/image/view/zip.cpp index cef9957b..d6fd9fd8 100644 --- a/tests/core/image/view/zip.cpp +++ b/tests/core/image/view/zip.cpp @@ -70,7 +70,10 @@ TEST(Core, ZipImage_Value_Iteration_1) static_assert(not concepts::RawImage); #endif // PYLENE_CONCEPT_TS_ENABLED - ::ranges::for_each(x.new_values(), [](std::tuple w) { w = std::make_tuple(2, 4); }); + // FIXME: + // ::ranges::for_each(x.new_values(), [](std::tuple w) { w = std::make_tuple(2, 4); }); + for (auto&& w : x.new_values()) + w = std::make_tuple(2, 4); ASSERT_TRUE(mln::all_of(a == 2)); ASSERT_TRUE(mln::all_of(b == 4)); @@ -96,7 +99,10 @@ TEST(Core, ZipImage_Pixel_Iteration_1) static_assert(not concepts::RawImage); #endif // PYLENE_CONCEPT_TS_ENABLED - ::ranges::for_each(x.new_pixels(), [](auto px) { px.val() = std::make_tuple(2, 4); }); + // FIXME: + // ::ranges::for_each(x.new_pixels(), [](auto px) { px.val() = std::make_tuple(2, 4); }); + for (auto&& w : x.new_values()) + w = std::make_tuple(2, 4); ASSERT_TRUE(mln::all_of(a == 2)); ASSERT_TRUE(mln::all_of(b == 4)); diff --git a/tests/core/image/zip_image.cpp b/tests/core/image/zip_image.cpp index 92769b15..ffeb8449 100644 --- a/tests/core/image/zip_image.cpp +++ b/tests/core/image/zip_image.cpp @@ -50,7 +50,11 @@ TEST(Core, ZipImage_Value_Iteration_1) image2d b(5, 5); auto x = view::zip(a, b); - ::ranges::for_each(x.new_values(), [](auto w) { w = std::make_tuple(2, 4); }); + // FIXME: + //::ranges::for_each(x.new_values(), [](auto w) { w = std::make_tuple(2, 4); }); + for (auto&& w : x.new_values()) + w = std::make_tuple(2, 4); + ASSERT_TRUE(all_of(a == 2)); ASSERT_TRUE(all_of(b == 4)); } @@ -64,7 +68,10 @@ TEST(Core, ZipImage_Pixel_Iteration_1) image2d b(5, 5); auto x = view::zip(a, b); - ::ranges::for_each(x.new_pixels(), [](auto x) { x.val() = std::make_tuple(2, 4); }); + // FIXME: + // ::ranges::for_each(x.new_pixels(), [](auto x) { x.val() = std::make_tuple(2, 4); }); + for (auto&& w : x.new_values()) + w = std::make_tuple(2, 4); ASSERT_TRUE(all_of(a == 2)); ASSERT_TRUE(all_of(b == 4)); -- GitLab From dd2c1df51a76fd7f2e85957ffccf3ea976373ad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Mon, 11 Mar 2019 13:32:52 +0100 Subject: [PATCH 04/61] revert algo fixes --- pylene/include/mln/core/algorithm/all_of.hpp | 9 ++------- pylene/include/mln/core/algorithm/any_of.hpp | 9 ++------- pylene/include/mln/core/algorithm/count.hpp | 7 +------ pylene/include/mln/core/algorithm/count_if.hpp | 7 +------ pylene/include/mln/core/algorithm/equal.hpp | 8 ++------ pylene/include/mln/core/algorithm/for_each.hpp | 6 +----- pylene/include/mln/core/algorithm/none_of.hpp | 10 ++-------- pylene/include/mln/core/algorithm/transform.hpp | 6 +----- tests/core/algorithm/paste.cpp | 7 +------ tests/core/image/view/zip.cpp | 10 ++-------- tests/core/image/zip_image.cpp | 10 ++-------- 11 files changed, 17 insertions(+), 72 deletions(-) diff --git a/pylene/include/mln/core/algorithm/all_of.hpp b/pylene/include/mln/core/algorithm/all_of.hpp index a471ce57..1181df02 100644 --- a/pylene/include/mln/core/algorithm/all_of.hpp +++ b/pylene/include/mln/core/algorithm/all_of.hpp @@ -26,14 +26,9 @@ namespace mln static_assert(::ranges::Predicate>()); auto&& vals = input.new_values(); - // FIXME: - // for (auto r : ranges::rows(vals)) - // if (!::ranges::all_of(r, p)) - // return false; for (auto r : ranges::rows(vals)) - for (auto&& v : r) - if (not std::invoke(p, v)) - return false; + if (!::ranges::all_of(r, p)) + return false; return true; } diff --git a/pylene/include/mln/core/algorithm/any_of.hpp b/pylene/include/mln/core/algorithm/any_of.hpp index 07c88b67..3a1ca34f 100644 --- a/pylene/include/mln/core/algorithm/any_of.hpp +++ b/pylene/include/mln/core/algorithm/any_of.hpp @@ -26,14 +26,9 @@ namespace mln static_assert(::ranges::Predicate>()); auto&& vals = input.new_values(); - // FIXME: - // for (auto r : ranges::rows(vals)) - // if (::ranges::any_of(r, p)) - // return true; for (auto r : ranges::rows(vals)) - for (auto&& v : r) - if (std::invoke(p, v)) - return true; + if (::ranges::any_of(r, p)) + return true; return false; } diff --git a/pylene/include/mln/core/algorithm/count.hpp b/pylene/include/mln/core/algorithm/count.hpp index be663dee..4af43a98 100644 --- a/pylene/include/mln/core/algorithm/count.hpp +++ b/pylene/include/mln/core/algorithm/count.hpp @@ -26,13 +26,8 @@ namespace mln auto&& vals = input.new_values(); std::ptrdiff_t k = 0; - // FIXME: - // for (auto r : ranges::rows(vals)) - // k += ::ranges::count(r, v); for (auto r : ranges::rows(vals)) - for (auto&& v : r) - if (v == val) - ++k; + k += ::ranges::count(r, val); return k; } diff --git a/pylene/include/mln/core/algorithm/count_if.hpp b/pylene/include/mln/core/algorithm/count_if.hpp index c2feff3a..decb2c5a 100644 --- a/pylene/include/mln/core/algorithm/count_if.hpp +++ b/pylene/include/mln/core/algorithm/count_if.hpp @@ -25,13 +25,8 @@ namespace mln auto&& vals = input.new_values(); std::ptrdiff_t k = 0; - // FIXME: - // for (auto r : ranges::rows(vals)) - // k += ::ranges::count_if(r, std::move(p)); for (auto r : ranges::rows(vals)) - for (auto&& v : r) - if (std::invoke(p, v)) - ++k; + k += ::ranges::count_if(r, std::move(p)); return k; } diff --git a/pylene/include/mln/core/algorithm/equal.hpp b/pylene/include/mln/core/algorithm/equal.hpp index 3ca3d6ca..e888d4d3 100644 --- a/pylene/include/mln/core/algorithm/equal.hpp +++ b/pylene/include/mln/core/algorithm/equal.hpp @@ -41,12 +41,8 @@ namespace mln for (auto [lhs_r, rhs_r] : ranges::view::zip(ranges::rows(lhs_vals), ranges::rows(rhs_vals))) // FIXME: with std::equal you gain performances over ranges::equal here - // FIXME: - // if (!::ranges::equal(lhs_r, rhs_r)) - // return false; - for (auto [lhs_v, rhs_v] : ranges::view::zip(lhs_r, rhs_r)) - if (not(lhs_v == rhs_v)) - return false; + if (!::ranges::equal(lhs_r, rhs_r)) + return false; return true; } diff --git a/pylene/include/mln/core/algorithm/for_each.hpp b/pylene/include/mln/core/algorithm/for_each.hpp index 30d84c4e..2e925e77 100644 --- a/pylene/include/mln/core/algorithm/for_each.hpp +++ b/pylene/include/mln/core/algorithm/for_each.hpp @@ -21,12 +21,8 @@ namespace mln static_assert(::ranges::Invocable>()); auto&& vals = input.new_values(); - // FIXME: - // for (auto r : ranges::rows(vals)) - // ::ranges::for_each(r, f); for (auto r : ranges::rows(vals)) - for (auto&& e : r) - std::invoke(f, e); + ::ranges::for_each(r, f); } } // namespace mln diff --git a/pylene/include/mln/core/algorithm/none_of.hpp b/pylene/include/mln/core/algorithm/none_of.hpp index 41183ba9..09634ee5 100644 --- a/pylene/include/mln/core/algorithm/none_of.hpp +++ b/pylene/include/mln/core/algorithm/none_of.hpp @@ -27,15 +27,9 @@ namespace mln static_assert(::ranges::Predicate>()); auto&& vals = input.new_values(); - // FIXME: - // for (auto r : ranges::rows(vals)) - // if (!::ranges::none_of(r, p)) - // return false; - for (auto r : ranges::rows(vals)) - for (auto&& v : r) - if (std::invoke(p, v)) - return false; + if (!::ranges::none_of(r, p)) + return false; return true; } diff --git a/pylene/include/mln/core/algorithm/transform.hpp b/pylene/include/mln/core/algorithm/transform.hpp index bd3f111f..e32505df 100644 --- a/pylene/include/mln/core/algorithm/transform.hpp +++ b/pylene/include/mln/core/algorithm/transform.hpp @@ -57,12 +57,8 @@ namespace mln auto&& ivals = in.new_values(); auto&& ovals = out.new_values(); - // FIXME: - // for (auto [r1, r2] : ranges::view::zip(ranges::rows(ivals), ranges::rows(ovals))) - // ::ranges::transform(r1, ::ranges::begin(r2), f); for (auto [r1, r2] : ranges::view::zip(ranges::rows(ivals), ranges::rows(ovals))) - for (auto&& [v1, v2] : ranges::view::zip(r1, r2)) - v2 = std::invoke(f, v1); + ::ranges::transform(r1, ::ranges::begin(r2), f); } template diff --git a/tests/core/algorithm/paste.cpp b/tests/core/algorithm/paste.cpp index bfaea523..27fee615 100644 --- a/tests/core/algorithm/paste.cpp +++ b/tests/core/algorithm/paste.cpp @@ -41,12 +41,7 @@ TEST(Core, Experimental_Algorithm_Paste) // 16 x x 19 // 31 x x 34 // 46 47 48 49 - - // FIXME: - // int r = ::ranges::accumulate(out.new_values(), 0); - int r = 0; - for (auto&& v : out.new_values()) - r += v; + int r = ::ranges::accumulate(out.new_values(), 0); ASSERT_EQ(r, 225 * 226 / 2 - (17 + 18 + 32 + 33) + 69 * 4); } diff --git a/tests/core/image/view/zip.cpp b/tests/core/image/view/zip.cpp index d6fd9fd8..cef9957b 100644 --- a/tests/core/image/view/zip.cpp +++ b/tests/core/image/view/zip.cpp @@ -70,10 +70,7 @@ TEST(Core, ZipImage_Value_Iteration_1) static_assert(not concepts::RawImage); #endif // PYLENE_CONCEPT_TS_ENABLED - // FIXME: - // ::ranges::for_each(x.new_values(), [](std::tuple w) { w = std::make_tuple(2, 4); }); - for (auto&& w : x.new_values()) - w = std::make_tuple(2, 4); + ::ranges::for_each(x.new_values(), [](std::tuple w) { w = std::make_tuple(2, 4); }); ASSERT_TRUE(mln::all_of(a == 2)); ASSERT_TRUE(mln::all_of(b == 4)); @@ -99,10 +96,7 @@ TEST(Core, ZipImage_Pixel_Iteration_1) static_assert(not concepts::RawImage); #endif // PYLENE_CONCEPT_TS_ENABLED - // FIXME: - // ::ranges::for_each(x.new_pixels(), [](auto px) { px.val() = std::make_tuple(2, 4); }); - for (auto&& w : x.new_values()) - w = std::make_tuple(2, 4); + ::ranges::for_each(x.new_pixels(), [](auto px) { px.val() = std::make_tuple(2, 4); }); ASSERT_TRUE(mln::all_of(a == 2)); ASSERT_TRUE(mln::all_of(b == 4)); diff --git a/tests/core/image/zip_image.cpp b/tests/core/image/zip_image.cpp index ffeb8449..04b77c73 100644 --- a/tests/core/image/zip_image.cpp +++ b/tests/core/image/zip_image.cpp @@ -50,10 +50,7 @@ TEST(Core, ZipImage_Value_Iteration_1) image2d b(5, 5); auto x = view::zip(a, b); - // FIXME: - //::ranges::for_each(x.new_values(), [](auto w) { w = std::make_tuple(2, 4); }); - for (auto&& w : x.new_values()) - w = std::make_tuple(2, 4); + ::ranges::for_each(x.new_values(), [](auto w) { w = std::make_tuple(2, 4); }); ASSERT_TRUE(all_of(a == 2)); ASSERT_TRUE(all_of(b == 4)); @@ -68,10 +65,7 @@ TEST(Core, ZipImage_Pixel_Iteration_1) image2d b(5, 5); auto x = view::zip(a, b); - // FIXME: - // ::ranges::for_each(x.new_pixels(), [](auto x) { x.val() = std::make_tuple(2, 4); }); - for (auto&& w : x.new_values()) - w = std::make_tuple(2, 4); + ::ranges::for_each(x.new_pixels(), [](auto x) { x.val() = std::make_tuple(2, 4); }); ASSERT_TRUE(all_of(a == 2)); ASSERT_TRUE(all_of(b == 4)); -- GitLab From 9b5ae7bbbf84881eaafef82b3de4ddf994cb089b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 12 Mar 2019 11:59:10 +0100 Subject: [PATCH 05/61] Switch to patched range-v3 recipe --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 585eea48..14689781 100644 --- a/conanfile.py +++ b/conanfile.py @@ -39,7 +39,7 @@ class Pylene(ConanFile): # Requirements part of the INTERFACE def requirements(self): - self.requires("range-v3/head@dutiona/testing") + self.requires("range-v3/head@dutiona/patched") self.requires("cmcstl2/head@dutiona/testing") if self.options.freeimage: -- GitLab From 8d9d4186215dc19c5ea4d52a3b3b12dd374eba45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 12 Mar 2019 16:00:56 +0100 Subject: [PATCH 06/61] Enable code following upgrade --- doc/source/snipsets/blobs_watershed.cpp | 4 +-- pylene/include/mln/core/algorithm/equal.hpp | 4 +++ .../mln/morpho/closing_by_reconstruction.hpp | 11 ++++++-- tests/core/image/image_ops.cpp | 22 ++++++--------- tests/core/image/sub_image.cpp | 4 +-- tests/core/image/view/transform.cpp | 28 ++++++++----------- 6 files changed, 34 insertions(+), 39 deletions(-) diff --git a/doc/source/snipsets/blobs_watershed.cpp b/doc/source/snipsets/blobs_watershed.cpp index f9afd745..dd82bf33 100644 --- a/doc/source/snipsets/blobs_watershed.cpp +++ b/doc/source/snipsets/blobs_watershed.cpp @@ -147,7 +147,5 @@ int main(int argc, char** argv) auto d_stretched = mln::data::stretch(d); mln::io::imsave(mln::transform(d_stretched, heat_lut), argv[2]); - - // FIXME: migrate rangev3 @HEAD - // mln::io::experimental::imsave(mln::transform(output, regions_lut), argv[3]); + mln::io::experimental::imsave(mln::transform(output, regions_lut), argv[3]); } diff --git a/pylene/include/mln/core/algorithm/equal.hpp b/pylene/include/mln/core/algorithm/equal.hpp index e888d4d3..eecdaefb 100644 --- a/pylene/include/mln/core/algorithm/equal.hpp +++ b/pylene/include/mln/core/algorithm/equal.hpp @@ -39,6 +39,10 @@ namespace mln auto&& lhs_vals = lhs.new_values(); auto&& rhs_vals = rhs.new_values(); + using RngLhs = ::ranges::iterator_t; + using RngRhs = ::ranges::iterator_t; + static_assert(::ranges::Comparable()); + for (auto [lhs_r, rhs_r] : ranges::view::zip(ranges::rows(lhs_vals), ranges::rows(rhs_vals))) // FIXME: with std::equal you gain performances over ranges::equal here if (!::ranges::equal(lhs_r, rhs_r)) diff --git a/pylene/include/mln/morpho/closing_by_reconstruction.hpp b/pylene/include/mln/morpho/closing_by_reconstruction.hpp index d26e7ea1..a9023ee5 100644 --- a/pylene/include/mln/morpho/closing_by_reconstruction.hpp +++ b/pylene/include/mln/morpho/closing_by_reconstruction.hpp @@ -1,7 +1,10 @@ #pragma once #include +#include #include +#include +#include #include #include @@ -63,9 +66,11 @@ namespace mln const J& markers = exact(markers_); // assert that f <= markers - mln_precondition(all(imtransform(imzip(f, markers), [cmp](std::tuple v) { - return not cmp(std::get<1>(v), std::get<0>(v)); - }))); + // FIXME: + // mln_precondition(all_of(view::transform(view::zip(f, markers), [cmp](std::tuple v) + // { + // return not cmp(std::get<1>(v), std::get<0>(v)); + // }))); mln_concrete(I) out = clone(f); mln_ch_value(I, accu_t) accus; diff --git a/tests/core/image/image_ops.cpp b/tests/core/image/image_ops.cpp index 1461abb7..da57ccc6 100644 --- a/tests/core/image/image_ops.cpp +++ b/tests/core/image/image_ops.cpp @@ -101,9 +101,7 @@ TEST(Core, Image2d_WhereOperator) auto f3 = experimental::where(x > 12, uint8_t(12), x); // RValue image + Scalar + LValue image auto f4 = experimental::where(x > 12, uint8_t(0), uint8_t(1)); // RValue image + Scalar + Scalar - // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 - // FIXME: migrate rangev3 @HEAD - // ASSERT_TRUE(mln::all_of(f1 >= 12)); + ASSERT_TRUE(mln::all_of(f1 >= 12)); static_assert(std::is_same_v, uint8_t>); static_assert(std::is_same_v, uint8_t&>); } @@ -197,12 +195,10 @@ TEST(Core, IfElse) static_assert(std::is_same_v, uint8_t>); static_assert(std::is_same_v, uint8_t>); - // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 - // FIXME: migrate rangev3 @HEAD - // ASSERT_TRUE(mln::all_of(f1 == ref_f1)); - // ASSERT_TRUE(mln::all_of(f2 == ref_f2)); - // ASSERT_TRUE(mln::all_of(f3 == ref_f3)); - // ASSERT_TRUE(mln::all_of(f4 == ref_f4)); + ASSERT_TRUE(mln::all_of(f1 == ref_f1)); + ASSERT_TRUE(mln::all_of(f2 == ref_f2)); + ASSERT_TRUE(mln::all_of(f3 == ref_f3)); + ASSERT_TRUE(mln::all_of(f4 == ref_f4)); image2d ref_x = {{1, 2, 3}, // @@ -210,12 +206,10 @@ TEST(Core, IfElse) image2d ref_y = {{42, 42, 42}, // {1, 2, 3}}; - // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 - // FIXME: migrate rangev3 @HEAD - // mln::fill(f2, 42); + mln::fill(f2, 42); - // ASSERT_TRUE(mln::all_of(x == ref_x)); - // ASSERT_TRUE(mln::all_of(y == ref_y)); + ASSERT_TRUE(mln::all_of(x == ref_x)); + ASSERT_TRUE(mln::all_of(y == ref_y)); } TEST(Core, Where) diff --git a/tests/core/image/sub_image.cpp b/tests/core/image/sub_image.cpp index 5e26c094..a9e9c9be 100644 --- a/tests/core/image/sub_image.cpp +++ b/tests/core/image/sub_image.cpp @@ -121,8 +121,8 @@ TEST(Core, SubImage_sub_domain) {20, 21, 22, 23, 24} // }; iota(ima, 0); - // mln::fill(view::clip(ima, experimental::where(ima > 10 && ima < 20)), 42); - // ASSERT_TRUE(all_of(ima == ref)); + mln::fill(view::clip(ima, experimental::where(ima > 10 && ima < 20)), 42); + ASSERT_TRUE(all_of(ima == ref)); } } diff --git a/tests/core/image/view/transform.cpp b/tests/core/image/view/transform.cpp index e9f49ce1..ffafefca 100644 --- a/tests/core/image/view/transform.cpp +++ b/tests/core/image/view/transform.cpp @@ -192,21 +192,20 @@ TEST(Core, Transform_Supports_Function) static_assert(not concepts::OutputImage); #endif // PYLENE_CONCEPT_TS_ENABLED - // FIXME: migrate rangev3 @HEAD - // ASSERT_TRUE(mln::equal(ref, c)); + ASSERT_TRUE(mln::equal(ref, c)); } TEST(Core, Transform_Supports_PointerToMemberFunction) { using namespace mln::experimental::ops; - typedef std::pair V; + using V = std::pair; mln::box2d dom{{-1, -2}, {3, 3}}; mln::image2d ima(dom, 3, std::make_pair(42, 42)); mln::image2d ref(dom, 3, std::make_pair(69, 42)); - auto c = mln::view::transform(ima, &std::pair::first); + auto c = mln::view::transform(ima, &V::first); #ifdef PYLENE_CONCEPT_TS_ENABLED static_assert(concepts::ConcreteImage); @@ -219,13 +218,9 @@ TEST(Core, Transform_Supports_PointerToMemberFunction) #endif // PYLENE_CONCEPT_TS_ENABLED mln::fill(c, 69); - - // FIXME: migrate rangev3 @HEAD - // ASSERT_TRUE(mln::equal(ref, c)); + ASSERT_TRUE(mln::equal(ima, ref)); } - -// TODO: add transform2 unit tests TEST(Core, Transformed2Image_transform_byval_chain) { using namespace mln; @@ -236,13 +231,12 @@ TEST(Core, Transformed2Image_transform_byval_chain) iota(ima, 0); iota(ima2, 1); - { - auto x = view::transform(ima, [](int a) { return a > 3; }); - auto y = view::transform(x, ima, [](bool a, int b) { return a ? b : 2; }); - [[maybe_unused]] auto out = view::transform(y, ima2, [](int a, int b) { return a + b; }); - // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 - // FIXME: migrate rangev3 @HEAD - // [[maybe_unused]] auto z = mln::all_of(out); - } + auto x = view::transform(ima, [](int a) { return a > 3; }); + auto y = view::transform(x, ima, [](bool a, int b) { return a ? b : 2; }); + auto out = view::transform(y, ima2, [](int a, int b) { return a + b; }); + + image2d ref(dom); + fill(ref, 3); + ASSERT_TRUE(mln::equal(out, ref)); } -- GitLab From 905c0c004ea203975621d60408c32f29f7d412be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 13 Mar 2019 15:59:59 +0100 Subject: [PATCH 07/61] Enable code following upgrade --- tests/core/image/image_ops.cpp | 17 +++++++++++------ tests/core/range/transform.cpp | 28 ++++++++++++++-------------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/tests/core/image/image_ops.cpp b/tests/core/image/image_ops.cpp index da57ccc6..91c97ca7 100644 --- a/tests/core/image/image_ops.cpp +++ b/tests/core/image/image_ops.cpp @@ -195,21 +195,26 @@ TEST(Core, IfElse) static_assert(std::is_same_v, uint8_t>); static_assert(std::is_same_v, uint8_t>); - ASSERT_TRUE(mln::all_of(f1 == ref_f1)); - ASSERT_TRUE(mln::all_of(f2 == ref_f2)); - ASSERT_TRUE(mln::all_of(f3 == ref_f3)); - ASSERT_TRUE(mln::all_of(f4 == ref_f4)); - - + // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 + // FIXME: migrate rangev3 @HEAD + // ASSERT_TRUE(mln::all_of(f1 == ref_f1)); + // ASSERT_TRUE(mln::all_of(f2 == ref_f2)); + // ASSERT_TRUE(mln::all_of(f3 == ref_f3)); + // ASSERT_TRUE(mln::all_of(f4 == ref_f4)); + + /* image2d ref_x = {{1, 2, 3}, // {42, 42, 42}}; image2d ref_y = {{42, 42, 42}, // {1, 2, 3}}; + // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 + // FIXME: migrate rangev3 @HEAD mln::fill(f2, 42); ASSERT_TRUE(mln::all_of(x == ref_x)); ASSERT_TRUE(mln::all_of(y == ref_y)); + */ } TEST(Core, Where) diff --git a/tests/core/range/transform.cpp b/tests/core/range/transform.cpp index 3107d1ae..9e3de54b 100644 --- a/tests/core/range/transform.cpp +++ b/tests/core/range/transform.cpp @@ -315,37 +315,37 @@ TEST(Range, transform_read_chain) mln::ranges::multi_span sp1(buffer1.data(), {3, 4}, {4, 1}); - auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); - auto y = mln::ranges::view::transform(x, [](int a) { return a + 1; }); + auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); + auto y = mln::ranges::view::transform(x, [](int a) { return a + 1; }); + [[maybe_unused]] auto z = mln::ranges::view::transform(y, [](int a) { return a * 2; }); -} + // TODO: add assert comparing +} -// FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 -// FIXME: migrate rangev3 @HEAD -/* TEST(Range, transform2_read_chain) { std::vector buffer1(12, -1); mln::ranges::multi_span sp1(buffer1.data(), {3, 4}, {4, 1}); - [[maybe_unused]] auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); - [[maybe_unused]] auto y = mln::ranges::view::transform(x, sp1, [](int a, int b) { return a + b; }); + auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); + auto y = mln::ranges::view::transform(x, sp1, [](int a, int b) { return a + b; }); + [[maybe_unused]] auto rng = mln::ranges::view::transform(y, [](int a) { return a + 1; }); + + // TODO: add assert comparing } -*/ -// FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 -// FIXME: migrate rangev3 @HEAD -/* TEST(Range, range_transform2_read_chain) { - std::vector buff(12, -1); + std::vector buff(12, -1); ::ranges::span sp(buff.data(), 12); auto x = ::ranges::view::transform(sp, [](int a) { return a > 3 ? a : 42; }); auto y = ::ranges::view::transform(x, sp, [](int a, int b) { return a + b; }); + [[maybe_unused]] auto rng = ::ranges::view::transform(y, [](int a) { return a + 1; }); + + // TODO: add assert comparing } -*/ -- GitLab From 1977278059bdb1bad543059e89d2d55bc1c9538c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 13 Mar 2019 16:54:21 +0100 Subject: [PATCH 08/61] Fix old bug in zip_with --- .../mln/core/image/private/image_operators.hpp | 5 +++-- .../include/mln/core/rangev3/view/zip_with.hpp | 9 +++------ tests/core/image/image_ops.cpp | 16 +++++----------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/pylene/include/mln/core/image/private/image_operators.hpp b/pylene/include/mln/core/image/private/image_operators.hpp index 121e9c83..798e4e51 100644 --- a/pylene/include/mln/core/image/private/image_operators.hpp +++ b/pylene/include/mln/core/image/private/image_operators.hpp @@ -98,8 +98,9 @@ namespace mln::experimental { auto operator()(const ICond& cond, ITrue iftrue, IFalse iffalse) const { - auto g = [](auto tuple_ternary_expr) -> decltype(auto) { - return (std::get<0>(tuple_ternary_expr)) ? std::get<1>(tuple_ternary_expr) : std::get<2>(tuple_ternary_expr); + auto g = [](auto&& tuple_ternary_expr) -> decltype(auto) { + auto&& [im_c, im_t, im_f] = std::forward(tuple_ternary_expr); + return im_c ? im_t : im_f; }; return view::transform(view::zip(cond, iftrue, iffalse), g); diff --git a/pylene/include/mln/core/rangev3/view/zip_with.hpp b/pylene/include/mln/core/rangev3/view/zip_with.hpp index 8765b3aa..fb84c976 100644 --- a/pylene/include/mln/core/rangev3/view/zip_with.hpp +++ b/pylene/include/mln/core/rangev3/view/zip_with.hpp @@ -89,18 +89,15 @@ namespace mln::ranges std::apply([](auto&... rng_it) { (++rng_it, ...); }, begins_); } - /* + #ifdef PYLENE_CONCEPT_TS_ENABLED // clang-format off void prev() requires (mln::concepts::stl::BidirectionalRange && ...) // clang-format on #else template () && ...)>> - - void prev() - #endif - */ void prev() +#endif { std::apply([](auto&... rng_it) { (--rng_it, ...); }, begins_); } @@ -250,7 +247,7 @@ namespace mln::ranges } - template + template #ifdef PYLENE_CONCEPT_TS_ENABLED // clang-format off auto zip_with_view::rows() requires (mln::concepts::SegmentedRange && ...) diff --git a/tests/core/image/image_ops.cpp b/tests/core/image/image_ops.cpp index 91c97ca7..0708c699 100644 --- a/tests/core/image/image_ops.cpp +++ b/tests/core/image/image_ops.cpp @@ -165,7 +165,6 @@ TEST(Core, BinaryOperators_MixedTypes) ASSERT_TRUE(mln::all_of(g3 == ref)); } - TEST(Core, IfElse) { using namespace mln; @@ -195,26 +194,21 @@ TEST(Core, IfElse) static_assert(std::is_same_v, uint8_t>); static_assert(std::is_same_v, uint8_t>); - // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 - // FIXME: migrate rangev3 @HEAD - // ASSERT_TRUE(mln::all_of(f1 == ref_f1)); - // ASSERT_TRUE(mln::all_of(f2 == ref_f2)); - // ASSERT_TRUE(mln::all_of(f3 == ref_f3)); - // ASSERT_TRUE(mln::all_of(f4 == ref_f4)); + ASSERT_TRUE(mln::all_of(f1 == ref_f1)); + ASSERT_TRUE(mln::all_of(f2 == ref_f2)); + ASSERT_TRUE(mln::all_of(f3 == ref_f3)); + ASSERT_TRUE(mln::all_of(f4 == ref_f4)); + - /* image2d ref_x = {{1, 2, 3}, // {42, 42, 42}}; image2d ref_y = {{42, 42, 42}, // {1, 2, 3}}; - // FIXME: issue https://github.com/ericniebler/range-v3/issues/996 with gcc8.2 - // FIXME: migrate rangev3 @HEAD mln::fill(f2, 42); ASSERT_TRUE(mln::all_of(x == ref_x)); ASSERT_TRUE(mln::all_of(y == ref_y)); - */ } TEST(Core, Where) -- GitLab From 353dfe16cfebec5ee12ccc45c800da3785fbc3cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 13 Mar 2019 17:10:05 +0100 Subject: [PATCH 09/61] Fix missing assert --- tests/core/range/transform.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/tests/core/range/transform.cpp b/tests/core/range/transform.cpp index 9e3de54b..037cc489 100644 --- a/tests/core/range/transform.cpp +++ b/tests/core/range/transform.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include @@ -308,7 +310,6 @@ TEST(Range, transform2_2d_write_row_wise) } } - TEST(Range, transform_read_chain) { std::vector buffer1(12, -1); @@ -317,10 +318,12 @@ TEST(Range, transform_read_chain) auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); auto y = mln::ranges::view::transform(x, [](int a) { return a + 1; }); + auto z = mln::ranges::view::transform(y, [](int a) { return a * 2; }); - [[maybe_unused]] auto z = mln::ranges::view::transform(y, [](int a) { return a * 2; }); + std::vector buffer_ref(12, 86); + mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); - // TODO: add assert comparing + ASSERT_TRUE(::ranges::equal(z, ref)); } TEST(Range, transform2_read_chain) @@ -331,10 +334,12 @@ TEST(Range, transform2_read_chain) auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); auto y = mln::ranges::view::transform(x, sp1, [](int a, int b) { return a + b; }); + auto z = mln::ranges::view::transform(y, [](int a) { return a + 1; }); - [[maybe_unused]] auto rng = mln::ranges::view::transform(y, [](int a) { return a + 1; }); + std::vector buffer_ref(12, 42); + mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); - // TODO: add assert comparing + ASSERT_TRUE(::ranges::equal(z, ref)); } TEST(Range, range_transform2_read_chain) @@ -344,8 +349,10 @@ TEST(Range, range_transform2_read_chain) auto x = ::ranges::view::transform(sp, [](int a) { return a > 3 ? a : 42; }); auto y = ::ranges::view::transform(x, sp, [](int a, int b) { return a + b; }); + auto z = ::ranges::view::transform(y, [](int a) { return a + 1; }); - [[maybe_unused]] auto rng = ::ranges::view::transform(y, [](int a) { return a + 1; }); + std::vector buffer_ref(12, 42); + ::ranges::span ref(buff.data(), 12); - // TODO: add assert comparing + ASSERT_TRUE(::ranges::equal(z, ref)); } -- GitLab From cdc1edd3ac60600dc603db28456de3401359d215 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 13 Mar 2019 17:41:12 +0100 Subject: [PATCH 10/61] Add fixme experimental --- doc/source/snipsets/staff_lines.cpp | 18 ++++++++++++------ .../mln/morpho/opening_by_reconstruction.hpp | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/doc/source/snipsets/staff_lines.cpp b/doc/source/snipsets/staff_lines.cpp index 6cf4bacc..190c1bed 100644 --- a/doc/source/snipsets/staff_lines.cpp +++ b/doc/source/snipsets/staff_lines.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -9,6 +10,8 @@ int main(int argc, char** argv) { + using namespace mln::experimental::ops; + if (argc < 7) { std::cerr << "Usage: " << argv[0] << " markers1.pbm markers2.pbm markers.pbm all.pbm lines.pbm\n"; @@ -31,7 +34,7 @@ int main(int argc, char** argv) auto se_miss = mln::se::make_se(se_miss_data); auto output = mln::morpho::hit_or_miss(input, se_hit, se_miss); markers1 = output; - mln::io::imsave(mln::lnot(markers1), argv[2]); + mln::io::experimental::imsave(not markers1, argv[2]); } { @@ -41,15 +44,18 @@ int main(int argc, char** argv) auto se_miss = mln::se::make_se(se_miss_data); auto output = mln::morpho::hit_or_miss(input, se_hit, se_miss); markers2 = output; - mln::io::imsave(mln::lnot(markers2), argv[3]); + mln::io::experimental::imsave(not markers2, argv[3]); } - auto markers = mln::lor(markers1, markers2); - mln::io::imsave(mln::lnot(markers), argv[4]); + auto markers = markers1 || markers2; + + mln::io::experimental::imsave(not markers, argv[4]); - auto all_touching = mln::morpho::opening_by_reconstruction(input, markers, mln::c4); + // FIXME: add experimental version + auto markers_ = mln::lor(markers1, markers2); + auto all_touching = mln::morpho::opening_by_reconstruction(input, markers_, mln::c4); mln::io::imsave(mln::lnot(all_touching), argv[5]); - auto lines_only = mln::morpho::opening_by_reconstruction(input, markers, mln::c2_h); + auto lines_only = mln::morpho::opening_by_reconstruction(input, markers_, mln::c2_h); mln::io::imsave(mln::lnot(lines_only), argv[6]); } diff --git a/pylene/include/mln/morpho/opening_by_reconstruction.hpp b/pylene/include/mln/morpho/opening_by_reconstruction.hpp index fbe00a49..d2ab6bb2 100644 --- a/pylene/include/mln/morpho/opening_by_reconstruction.hpp +++ b/pylene/include/mln/morpho/opening_by_reconstruction.hpp @@ -26,6 +26,7 @@ namespace mln "Images f and marker must have the same point type."); mln_entering("mln::morpho::opening_by_reconstruction"); + // FIXME: add experimental version return closing_by_reconstruction(f, markers, nbh, std::greater()); } } // namespace morpho -- GitLab From 732a2bff05d966a9144fd13fb7ee984cecf3748d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 15 Mar 2019 10:29:29 +0100 Subject: [PATCH 11/61] WIP --- .gitlab-ci.yml | 2 +- pylene/include/mln/core/rangev3/view/zip_with.hpp | 4 +++- tests/core/image/view/transform.cpp | 6 ++++++ tests/core/range/transform.cpp | 10 ++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6c9efe2f..52d09d48 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ before_script: - cmake --build apps --config $PYLENE_CONFIGURATION - cmake --build tests --config $PYLENE_CONFIGURATION - cmake --build bench/tests --config $PYLENE_CONFIGURATION - - ctest -L UnitTests --schedule-random --output-on-failure + - ctest -L UnitTests -V --schedule-random --output-on-failure dependencies: [] artifacts: reports: diff --git a/pylene/include/mln/core/rangev3/view/zip_with.hpp b/pylene/include/mln/core/rangev3/view/zip_with.hpp index fb84c976..0f869cd8 100644 --- a/pylene/include/mln/core/rangev3/view/zip_with.hpp +++ b/pylene/include/mln/core/rangev3/view/zip_with.hpp @@ -95,7 +95,9 @@ namespace mln::ranges void prev() requires (mln::concepts::stl::BidirectionalRange && ...) // clang-format on #else - template () && ...)>> + template {}>...>, + void*> = nullptr> void prev() #endif { diff --git a/tests/core/image/view/transform.cpp b/tests/core/image/view/transform.cpp index ffafefca..f5fa8c55 100644 --- a/tests/core/image/view/transform.cpp +++ b/tests/core/image/view/transform.cpp @@ -14,6 +14,8 @@ #include +#include + #include @@ -238,5 +240,9 @@ TEST(Core, Transformed2Image_transform_byval_chain) image2d ref(dom); fill(ref, 3); + + for (auto&& v : out.new_values()) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(mln::equal(out, ref)); } diff --git a/tests/core/range/transform.cpp b/tests/core/range/transform.cpp index 037cc489..f6368ca2 100644 --- a/tests/core/range/transform.cpp +++ b/tests/core/range/transform.cpp @@ -6,6 +6,7 @@ #include +#include #include #include @@ -323,6 +324,9 @@ TEST(Range, transform_read_chain) std::vector buffer_ref(12, 86); mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); + for (auto&& v : z) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(::ranges::equal(z, ref)); } @@ -339,6 +343,9 @@ TEST(Range, transform2_read_chain) std::vector buffer_ref(12, 42); mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); + for (auto&& v : z) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(::ranges::equal(z, ref)); } @@ -354,5 +361,8 @@ TEST(Range, range_transform2_read_chain) std::vector buffer_ref(12, 42); ::ranges::span ref(buff.data(), 12); + for (auto&& v : z) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(::ranges::equal(z, ref)); } -- GitLab From 4acfb6b5069090e5bbce8a0950977b692af87ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 15 Mar 2019 12:14:01 +0100 Subject: [PATCH 12/61] WIP --- tests/core/image/morphers/filtered_image.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/core/image/morphers/filtered_image.cpp b/tests/core/image/morphers/filtered_image.cpp index 4280dc6b..054cef2d 100644 --- a/tests/core/image/morphers/filtered_image.cpp +++ b/tests/core/image/morphers/filtered_image.cpp @@ -86,7 +86,8 @@ TEST(Core, FilteredImage_filtered_chaining) auto x = view::filter(ima, [](int v) { return v > 10; }); auto u = view::filter(x, [](int v) { return v < 15; }); - ASSERT_TRUE(all_of(u > 10 && u < 15)); + // FIXME: + // ASSERT_TRUE(all_of(u > 10 && u < 15)); { for (auto&& pix : ima.new_pixels()) -- GitLab From f822d5a97e7fdc3af363134c0c978f45745cab93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 15 Mar 2019 13:10:51 +0100 Subject: [PATCH 13/61] WIP --- tests/core/image/view/transform.cpp | 3 +-- tests/core/range/transform.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/tests/core/image/view/transform.cpp b/tests/core/image/view/transform.cpp index f5fa8c55..62175b19 100644 --- a/tests/core/image/view/transform.cpp +++ b/tests/core/image/view/transform.cpp @@ -238,8 +238,7 @@ TEST(Core, Transformed2Image_transform_byval_chain) auto y = view::transform(x, ima, [](bool a, int b) { return a ? b : 2; }); auto out = view::transform(y, ima2, [](int a, int b) { return a + b; }); - image2d ref(dom); - fill(ref, 3); + image2d ref = {{3, 4, 5, 6}, {9, 11, 13, 15}, {17, 19, 21, 23}, {25, 27, 29, 31}, {33, 35, 37, 39}}; for (auto&& v : out.new_values()) std::cout << v << ", " << std::endl; diff --git a/tests/core/range/transform.cpp b/tests/core/range/transform.cpp index f6368ca2..ffd2c5e3 100644 --- a/tests/core/range/transform.cpp +++ b/tests/core/range/transform.cpp @@ -324,9 +324,14 @@ TEST(Range, transform_read_chain) std::vector buffer_ref(12, 86); mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); + std::cout << "z:" << std::endl; for (auto&& v : z) std::cout << v << ", " << std::endl; + std::cout << "ref:" << std::endl; + for (auto&& v : ref) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(::ranges::equal(z, ref)); } @@ -343,9 +348,14 @@ TEST(Range, transform2_read_chain) std::vector buffer_ref(12, 42); mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); + std::cout << "z:" << std::endl; for (auto&& v : z) std::cout << v << ", " << std::endl; + std::cout << "ref:" << std::endl; + for (auto&& v : ref) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(::ranges::equal(z, ref)); } @@ -361,8 +371,13 @@ TEST(Range, range_transform2_read_chain) std::vector buffer_ref(12, 42); ::ranges::span ref(buff.data(), 12); + std::cout << "z:" << std::endl; for (auto&& v : z) std::cout << v << ", " << std::endl; + std::cout << "ref:" << std::endl; + for (auto&& v : ref) + std::cout << v << ", " << std::endl; + ASSERT_TRUE(::ranges::equal(z, ref)); } -- GitLab From dd7fb93d7dc00b562388f303a15561b676600084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 15 Mar 2019 13:43:54 +0100 Subject: [PATCH 14/61] Fix clang compilation (fix zip_with clunky SFINAE) --- .../mln/core/rangev3/view/zip_with.hpp | 25 ++++++++--- tests/core/image/morphers/filtered_image.cpp | 3 +- tests/core/image/view/transform.cpp | 9 ++-- tests/core/range/transform.cpp | 45 +++++-------------- 4 files changed, 34 insertions(+), 48 deletions(-) diff --git a/pylene/include/mln/core/rangev3/view/zip_with.hpp b/pylene/include/mln/core/rangev3/view/zip_with.hpp index 0f869cd8..57b780dc 100644 --- a/pylene/include/mln/core/rangev3/view/zip_with.hpp +++ b/pylene/include/mln/core/rangev3/view/zip_with.hpp @@ -50,6 +50,7 @@ namespace mln::ranges using fun_ref_ = ::ranges::semiregular_ref_or_val_t; fun_ref_ fun_; std::tuple<::ranges::iterator_t...> begins_; + static inline constexpr const bool are_bidir_rngs_ = (::ranges::BidirectionalRange() && ...); public: cursor() = default; @@ -89,20 +90,34 @@ namespace mln::ranges std::apply([](auto&... rng_it) { (++rng_it, ...); }, begins_); } - #ifdef PYLENE_CONCEPT_TS_ENABLED // clang-format off void prev() requires (mln::concepts::stl::BidirectionalRange && ...) // clang-format on + { + std::apply([](auto&... rng_it) { (--rng_it, ...); }, begins_); + } #else - template {}>...>, - void*> = nullptr> + // Clunky SFINAE doesn't work + /* + template () && ...)>> void prev() -#endif { std::apply([](auto&... rng_it) { (--rng_it, ...); }, begins_); } + */ + void prev() + { + if constexpr (are_bidir_rngs_) + { + std::apply([](auto&... rng_it) { (--rng_it, ...); }, begins_); + } + else + { + static_assert(are_bidir_rngs_, "Cannot traverse non-bidirectional range backward"); + } + } +#endif }; cursor begin_cursor() diff --git a/tests/core/image/morphers/filtered_image.cpp b/tests/core/image/morphers/filtered_image.cpp index 054cef2d..4280dc6b 100644 --- a/tests/core/image/morphers/filtered_image.cpp +++ b/tests/core/image/morphers/filtered_image.cpp @@ -86,8 +86,7 @@ TEST(Core, FilteredImage_filtered_chaining) auto x = view::filter(ima, [](int v) { return v > 10; }); auto u = view::filter(x, [](int v) { return v < 15; }); - // FIXME: - // ASSERT_TRUE(all_of(u > 10 && u < 15)); + ASSERT_TRUE(all_of(u > 10 && u < 15)); { for (auto&& pix : ima.new_pixels()) diff --git a/tests/core/image/view/transform.cpp b/tests/core/image/view/transform.cpp index 62175b19..dc852152 100644 --- a/tests/core/image/view/transform.cpp +++ b/tests/core/image/view/transform.cpp @@ -14,7 +14,7 @@ #include -#include +#include #include @@ -238,10 +238,7 @@ TEST(Core, Transformed2Image_transform_byval_chain) auto y = view::transform(x, ima, [](bool a, int b) { return a ? b : 2; }); auto out = view::transform(y, ima2, [](int a, int b) { return a + b; }); - image2d ref = {{3, 4, 5, 6}, {9, 11, 13, 15}, {17, 19, 21, 23}, {25, 27, 29, 31}, {33, 35, 37, 39}}; + std::vector ref = {3, 4, 5, 6, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39}; - for (auto&& v : out.new_values()) - std::cout << v << ", " << std::endl; - - ASSERT_TRUE(mln::equal(out, ref)); + ASSERT_EQ(ref, ::ranges::to_vector(out.new_values())); } diff --git a/tests/core/range/transform.cpp b/tests/core/range/transform.cpp index ffd2c5e3..3b355da5 100644 --- a/tests/core/range/transform.cpp +++ b/tests/core/range/transform.cpp @@ -6,7 +6,6 @@ #include -#include #include #include @@ -313,48 +312,32 @@ TEST(Range, transform2_2d_write_row_wise) TEST(Range, transform_read_chain) { - std::vector buffer1(12, -1); + std::vector buffer(12, -1); - mln::ranges::multi_span sp1(buffer1.data(), {3, 4}, {4, 1}); + mln::ranges::multi_span sp(buffer.data(), {3, 4}, {4, 1}); - auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); + auto x = mln::ranges::view::transform(sp, [](int a) { return a > 3 ? a : 42; }); auto y = mln::ranges::view::transform(x, [](int a) { return a + 1; }); auto z = mln::ranges::view::transform(y, [](int a) { return a * 2; }); std::vector buffer_ref(12, 86); - mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); - - std::cout << "z:" << std::endl; - for (auto&& v : z) - std::cout << v << ", " << std::endl; - - std::cout << "ref:" << std::endl; - for (auto&& v : ref) - std::cout << v << ", " << std::endl; + mln::ranges::multi_span ref(buffer_ref.data(), {3, 4}, {4, 1}); ASSERT_TRUE(::ranges::equal(z, ref)); } TEST(Range, transform2_read_chain) { - std::vector buffer1(12, -1); + std::vector buffer(12, -1); - mln::ranges::multi_span sp1(buffer1.data(), {3, 4}, {4, 1}); + mln::ranges::multi_span sp(buffer.data(), {3, 4}, {4, 1}); - auto x = mln::ranges::view::transform(sp1, [](int a) { return a > 3 ? a : 42; }); - auto y = mln::ranges::view::transform(x, sp1, [](int a, int b) { return a + b; }); + auto x = mln::ranges::view::transform(sp, [](int a) { return a > 3 ? a : 42; }); + auto y = mln::ranges::view::transform(x, sp, [](int a, int b) { return a + b; }); auto z = mln::ranges::view::transform(y, [](int a) { return a + 1; }); std::vector buffer_ref(12, 42); - mln::ranges::multi_span ref(buffer1.data(), {3, 4}, {4, 1}); - - std::cout << "z:" << std::endl; - for (auto&& v : z) - std::cout << v << ", " << std::endl; - - std::cout << "ref:" << std::endl; - for (auto&& v : ref) - std::cout << v << ", " << std::endl; + mln::ranges::multi_span ref(buffer_ref.data(), {3, 4}, {4, 1}); ASSERT_TRUE(::ranges::equal(z, ref)); } @@ -369,15 +352,7 @@ TEST(Range, range_transform2_read_chain) auto z = ::ranges::view::transform(y, [](int a) { return a + 1; }); std::vector buffer_ref(12, 42); - ::ranges::span ref(buff.data(), 12); - - std::cout << "z:" << std::endl; - for (auto&& v : z) - std::cout << v << ", " << std::endl; - - std::cout << "ref:" << std::endl; - for (auto&& v : ref) - std::cout << v << ", " << std::endl; + ::ranges::span ref(buffer_ref.data(), 12); ASSERT_TRUE(::ranges::equal(z, ref)); } -- GitLab From 6c25e61b78e4efff9e91e72a16bd59e07afee48d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Thu, 21 Mar 2019 17:41:44 +0100 Subject: [PATCH 15/61] WIP --- .../mln/core/image/private/def_gen_macros.hpp | 48 +++++++++++++++++++ .../core/image/private/undef_gen_macros.hpp | 3 ++ pylene/include/mln/core/image/view/maths.hpp | 8 ++++ .../include/mln/core/image/view/operators.hpp | 48 ++----------------- 4 files changed, 62 insertions(+), 45 deletions(-) create mode 100644 pylene/include/mln/core/image/private/def_gen_macros.hpp create mode 100644 pylene/include/mln/core/image/private/undef_gen_macros.hpp create mode 100644 pylene/include/mln/core/image/view/maths.hpp diff --git a/pylene/include/mln/core/image/private/def_gen_macros.hpp b/pylene/include/mln/core/image/private/def_gen_macros.hpp new file mode 100644 index 00000000..80f9ca1e --- /dev/null +++ b/pylene/include/mln/core/image/private/def_gen_macros.hpp @@ -0,0 +1,48 @@ +#include +#include +#include + +#include + + +#define MLN_PRIVATE_DEFINE_UNARY_OPERATOR(op, f) \ + template ::value>> \ + auto op(const I& ima) \ + { \ + return ::mln::view::transform(static_cast(ima), f); \ + } + +#define MLN_PRIVATE_DEFINE_BINARY_OPERATOR(op, f) \ + namespace impl \ + { \ + template \ + auto op(const ::mln::experimental::Image& ima1, const ::mln::experimental::Image& ima2) \ + { \ + return ::mln::view::transform(static_cast(ima1), static_cast(ima2), f); \ + } \ + \ + template ::value>> \ + auto op(const ::mln::experimental::Image& ima1, Scalar s) \ + { \ + auto g = [f_ = f, s_ = s](auto&& arg) { return f_(arg, s_); }; \ + return ::mln::view::transform(static_cast(ima1), g); \ + } \ + \ + template ::value>> \ + auto op(Scalar s, const ::mln::experimental::Image& ima2) \ + { \ + auto g = [f_ = f, s_ = s](auto&& arg) { return f_(s_, arg); }; \ + return ::mln::view::transform(static_cast(ima2), g); \ + } \ + } /* namespace impl */ \ + \ + /* This overload is there to be a best match wrt old API impl */ \ + template ::value || \ + ::mln::is_a::value)>> \ + auto op(const A& lhs, const B& rhs) \ + { \ + return impl::op(lhs, rhs); \ + } diff --git a/pylene/include/mln/core/image/private/undef_gen_macros.hpp b/pylene/include/mln/core/image/private/undef_gen_macros.hpp new file mode 100644 index 00000000..3156bf11 --- /dev/null +++ b/pylene/include/mln/core/image/private/undef_gen_macros.hpp @@ -0,0 +1,3 @@ + +#undef MLN_PRIVATE_DEFINE_UNARY_OPERATOR +#undef MLN_PRIVATE_DEFINE_BINARY_OPERATOR diff --git a/pylene/include/mln/core/image/view/maths.hpp b/pylene/include/mln/core/image/view/maths.hpp new file mode 100644 index 00000000..19e76053 --- /dev/null +++ b/pylene/include/mln/core/image/view/maths.hpp @@ -0,0 +1,8 @@ +namespace mln::view +{ + + namespace ops + { + } + +} // namespace mln::view diff --git a/pylene/include/mln/core/image/view/operators.hpp b/pylene/include/mln/core/image/view/operators.hpp index 59618a1e..30614f09 100644 --- a/pylene/include/mln/core/image/view/operators.hpp +++ b/pylene/include/mln/core/image/view/operators.hpp @@ -6,57 +6,16 @@ #include +#include namespace mln::view { // Prevent ADL on those operators so that A+B uses old API - // and using mln::experimental::ops A+B uses new API + // and using mln::view::ops A+B uses new API // to be reverted when the new API is validated namespace ops { -#define MLN_PRIVATE_DEFINE_UNARY_OPERATOR(op, f) \ - template ::value>> \ - auto op(const I& ima) \ - { \ - return view::transform(static_cast(ima), f); \ - } - - -#define MLN_PRIVATE_DEFINE_BINARY_OPERATOR(op, f) \ - namespace impl \ - { \ - template \ - auto op(const mln::experimental::Image& ima1, const mln::experimental::Image& ima2) \ - { \ - return view::transform(static_cast(ima1), static_cast(ima2), f); \ - } \ - \ - template ::value>> \ - auto op(const mln::experimental::Image& ima1, Scalar s) \ - { \ - auto g = [f_ = f, s_ = s](auto&& arg) { return f_(arg, s_); }; \ - return view::transform(static_cast(ima1), g); \ - } \ - \ - template ::value>> \ - auto op(Scalar s, const mln::experimental::Image& ima2) \ - { \ - auto g = [f_ = f, s_ = s](auto&& arg) { return f_(s_, arg); }; \ - return view::transform(static_cast(ima2), g); \ - } \ - } \ - \ - /* This overload is there to be a best match wrt old API impl */ \ - template ::value || \ - is_a::value)>> \ - auto op(const A& lhs, const B& rhs) \ - { \ - return mln::view::ops::impl::op(lhs, rhs); \ - } - - namespace details { template @@ -164,7 +123,6 @@ namespace mln::view std::move(iffalse)); } -#undef MLN_PRIVATE_DEFINE_UNARY_OPERATOR -#undef MLN_PRIVATE_DEFINE_BINARY_OPERATOR +#include } // namespace mln::view -- GitLab From f8d05225cf502b217c1b072da1649ff667e6ac4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 29 Mar 2019 13:22:24 +0100 Subject: [PATCH 16/61] Move operators tests --- tests/core/CMakeLists.txt | 2 +- tests/core/image/{image_ops.cpp => view/operators.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/core/image/{image_ops.cpp => view/operators.cpp} (100%) diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 5cb7e60e..40f9953d 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -23,6 +23,7 @@ add_core_test(${test_prefix}view_filter image/view/filter.cpp) add_core_test(${test_prefix}view_clip image/view/clip.cpp) add_core_test(${test_prefix}view_mask image/view/mask.cpp) add_core_test(${test_prefix}view_zip image/view/zip.cpp) +add_core_test(${test_prefix}view_ops image/view/operators.cpp) # test Images @@ -33,7 +34,6 @@ add_core_test(${test_prefix}transformed_image image/morphers/transformed_i add_core_test(${test_prefix}filtered_image image/morphers/filtered_image.cpp) add_core_test(${test_prefix}zip_image image/zip_image.cpp) add_core_test(${test_prefix}sub_image image/sub_image.cpp) -add_core_test(${test_prefix}image_ops image/image_ops.cpp) add_core_test(${test_prefix}image_routines image/image_routines.cpp) add_core_test(${test_prefix}image_ndimage image/ndimage.cpp) add_core_test(${test_prefix}image_private_ndpixel image/private/ndimage_pixel.cpp) diff --git a/tests/core/image/image_ops.cpp b/tests/core/image/view/operators.cpp similarity index 100% rename from tests/core/image/image_ops.cpp rename to tests/core/image/view/operators.cpp -- GitLab From af1bc36a45e6d64d9771857e947ae624287402d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 2 Apr 2019 16:14:47 +0200 Subject: [PATCH 17/61] Add view::cast unit test Add maths operators into views (+tests) Add views.hpp file --- pylene/include/mln/core/image/view/maths.hpp | 26 ++++++++++++++-- .../include/mln/core/image/view/operators.hpp | 3 ++ pylene/include/mln/core/image/views.hpp | 11 +++++++ pylene/include/mln/core/rangev3/views.hpp | 8 +++++ tests/core/CMakeLists.txt | 8 +++-- tests/core/image/view/cast.cpp | 30 +++++++++++++++++++ tests/core/image/view/clip.cpp | 21 +++++++++++++ tests/core/image/view/maths.cpp | 19 ++++++++++++ 8 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 pylene/include/mln/core/image/views.hpp create mode 100644 pylene/include/mln/core/rangev3/views.hpp create mode 100644 tests/core/image/view/cast.cpp create mode 100644 tests/core/image/view/maths.cpp diff --git a/pylene/include/mln/core/image/view/maths.hpp b/pylene/include/mln/core/image/view/maths.hpp index 19e76053..8b7e10e5 100644 --- a/pylene/include/mln/core/image/view/maths.hpp +++ b/pylene/include/mln/core/image/view/maths.hpp @@ -1,8 +1,30 @@ +#pragma once + +#include + +#include + namespace mln::view { - namespace ops + namespace maths { - } + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(abs, functional::abs_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sqr, functional::sqr_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(pow, functional::pow_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sqrt, functional::sqrt_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(cbrt, functional::cbrt_t<>()); + + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sum, functional::sum_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(prod, functional::prod_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l0norm, functional::l0norm_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l1norm, functional::l1norm_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l2norm, functional::l2norm_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(linfnorm, functional::linfnorm_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l1dist, functional::l1dist_t<>()); + + } // namespace maths } // namespace mln::view + +#include diff --git a/pylene/include/mln/core/image/view/operators.hpp b/pylene/include/mln/core/image/view/operators.hpp index 30614f09..089c77d4 100644 --- a/pylene/include/mln/core/image/view/operators.hpp +++ b/pylene/include/mln/core/image/view/operators.hpp @@ -1,10 +1,13 @@ #pragma once +#include #include #include #include #include +#include +#include #include diff --git a/pylene/include/mln/core/image/views.hpp b/pylene/include/mln/core/image/views.hpp new file mode 100644 index 00000000..b918471a --- /dev/null +++ b/pylene/include/mln/core/image/views.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/pylene/include/mln/core/rangev3/views.hpp b/pylene/include/mln/core/rangev3/views.hpp new file mode 100644 index 00000000..9f751e4f --- /dev/null +++ b/pylene/include/mln/core/rangev3/views.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include +#include +#include +#include +#include +#include diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 40f9953d..6ff2a1c9 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -18,12 +18,14 @@ 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) -add_core_test(${test_prefix}view_filter image/view/filter.cpp) +add_core_test(${test_prefix}view_cast image/view/cast.cpp) add_core_test(${test_prefix}view_clip image/view/clip.cpp) +add_core_test(${test_prefix}view_filter image/view/filter.cpp) add_core_test(${test_prefix}view_mask image/view/mask.cpp) -add_core_test(${test_prefix}view_zip image/view/zip.cpp) +add_core_test(${test_prefix}view_maths image/view/maths.cpp) add_core_test(${test_prefix}view_ops image/view/operators.cpp) +add_core_test(${test_prefix}view_transform image/view/transform.cpp) +add_core_test(${test_prefix}view_zip image/view/zip.cpp) # test Images diff --git a/tests/core/image/view/cast.cpp b/tests/core/image/view/cast.cpp new file mode 100644 index 00000000..26ea6a05 --- /dev/null +++ b/tests/core/image/view/cast.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include + +#include + + +TEST(View, cast) +{ + using namespace mln; + using namespace view::ops; + + image2d ima = {{0.1, 1.2, 2.3, 3.4, 4.5}, // + {5.6, 6.7, 4.8, 8.7, 9.6}, // + {10.5, 11.4, 12.3, 13.2, 14.1}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + auto casted_ima = view::cast(ima); + ASSERT_TRUE(all_of(ima == ref)); + + image2d ima2 = {{0.1, 0.2, 0.3, 0.4, 0.5}, // + {0.6, 0.7, 0.8, 0.7, 0.6}, // + {0.5, 0.4, 0.3, 0.2, 0.1}}; + + ASSERT_TRUE(all_of(ima == casted_ima + ima2)); +} diff --git a/tests/core/image/view/clip.cpp b/tests/core/image/view/clip.cpp index a42d82f5..700917b9 100644 --- a/tests/core/image/view/clip.cpp +++ b/tests/core/image/view/clip.cpp @@ -180,6 +180,27 @@ TEST(Core, Clip_wherex2_joints) ASSERT_TRUE(all_of(ima == ref)); } +TEST(Core, Clip_wherex2_disjoints) +{ + using namespace mln; + using namespace mln::view::ops; + + image2d ima(5, 5); + + image2d ref = { + {0, 1, 2, 3, 4}, // + {5, 6, 7, 8, 9}, // + {10, 42, 42, 42, 42}, // + {42, 42, 42, 42, 42}, // + {20, 21, 22, 23, 24} // + }; + + mln::iota(ima, 0); + auto clipped_ima = view::clip(ima, experimental::where(ima > 10)); + mln::fill(view::clip(clipped_ima, experimental::where(clipped_ima < 20)), 42); + ASSERT_TRUE(all_of(ima == ref)); +} + TEST(Core, Clip_where_and) { using namespace mln; diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp new file mode 100644 index 00000000..33a290fe --- /dev/null +++ b/tests/core/image/view/maths.cpp @@ -0,0 +1,19 @@ +#include +#include +#include +#include + +#include + + +TEST(View, maths) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + [[maybe_unused]] image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; +} -- GitLab From b90f89437a238f9d93ecd4de76285a3f921241b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 2 Apr 2019 16:32:49 +0200 Subject: [PATCH 18/61] Write test for abs, sqr, pow, sqrt, cbrt TODO: sm, prod, l0norm, l1norm, l2norm, linfnorm, ldist --- tests/core/image/view/maths.cpp | 78 +++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 33a290fe..12427166 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -2,18 +2,88 @@ #include #include #include +#include #include -TEST(View, maths) +TEST(View, maths_abs) { using namespace mln; using namespace view::ops; using namespace view::maths; - [[maybe_unused]] image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == abs(ima))); +} + +TEST(View, maths_sqr) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + image2d ref = {{0, 1, 4, 9, 16}, // + {25, 36, 16, 64, 81}, // + {100, 121, 144, 169, 196}}; + + ASSERT_TRUE(all_of(ref == sqr(ima))); +} + +TEST(View, maths_pow) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + auto ima = view::transform(ref, [](auto x) { return x * x * x; }); + + ASSERT_TRUE(all_of(pow(ref, 3) == ima)); +} + +TEST(View, maths_sqrt) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, 1, 4, 9, 16}, // + {25, 36, 16, 64, 81}, // + {100, 121, 144, 169, 196}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == sqrt(ima))); +} + +TEST(View, maths_cbrt) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + auto ima = pow(ref, 3); + + ASSERT_TRUE(all_of(ref == cbrt(ima))); } -- GitLab From 6e564631f1cce46381dab37da9b221695e3535ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 00:41:44 +0200 Subject: [PATCH 19/61] Fix unit tests --- tests/core/image/view/cast.cpp | 2 +- tests/core/image/view/maths.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/core/image/view/cast.cpp b/tests/core/image/view/cast.cpp index 26ea6a05..da3ed718 100644 --- a/tests/core/image/view/cast.cpp +++ b/tests/core/image/view/cast.cpp @@ -20,7 +20,7 @@ TEST(View, cast) {10, 11, 12, 13, 14}}; auto casted_ima = view::cast(ima); - ASSERT_TRUE(all_of(ima == ref)); + ASSERT_TRUE(all_of(casted_ima == ref)); image2d ima2 = {{0.1, 0.2, 0.3, 0.4, 0.5}, // {0.6, 0.7, 0.8, 0.7, 0.6}, // diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 12427166..21aebbd0 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -85,5 +85,6 @@ TEST(View, maths_cbrt) {10, 11, 12, 13, 14}}; auto ima = pow(ref, 3); - ASSERT_TRUE(all_of(ref == cbrt(ima))); + // FIXME: + // ASSERT_TRUE(all_of(ref == cbrt(ima))); } -- GitLab From 348b53422b4a89d74feda72f7b473ffe5fde9c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 15:24:45 +0200 Subject: [PATCH 20/61] Implement cached view::filter::domain::size --- pylene/include/mln/core/image/view/filter.hpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pylene/include/mln/core/image/view/filter.hpp b/pylene/include/mln/core/image/view/filter.hpp index f55882e0..4524e59b 100644 --- a/pylene/include/mln/core/image/view/filter.hpp +++ b/pylene/include/mln/core/image/view/filter.hpp @@ -58,6 +58,24 @@ namespace mln bool has(point_type p) const { return m_dom.has(p) && m_fun(p); } bool empty() const { return ::ranges::empty(m_rng); } + + auto size() const + { + static std::size_t size = 0; + static bool computed = false; + if (!computed) + { + auto b = begin(); + auto e = end(); + while (b != e) + { + ++size; + ++b; + } + computed = true; + } + return size; + } }; /// \} -- GitLab From 48ea3417ffb274a80bf54fbfa8eac2ab47862ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 15:25:01 +0200 Subject: [PATCH 21/61] Fix typo --- pylene/include/mln/io/saver.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylene/include/mln/io/saver.hpp b/pylene/include/mln/io/saver.hpp index a00469eb..5b553748 100644 --- a/pylene/include/mln/io/saver.hpp +++ b/pylene/include/mln/io/saver.hpp @@ -69,7 +69,7 @@ namespace mln void Saver::save_experimental(I ima, PluginWriter* plugin, bool permissive) const { static_assert(is_a()); - + if (not plugin->can_write(typeid(mln_value(I)))) { std::string msg = "The plugin does not support writing " + internal::demangle(typeid(mln_value(I)).name()); @@ -89,7 +89,7 @@ namespace mln // FIXME: Oh my! So dirty! // To be fixed with new io facility based on type-erased image for python - if constexpr (is_a{}) + if constexpr (mln::is_a{}) { for (auto v : const_cast(&ima)->new_values()) { -- GitLab From 69a131fd43bcdf6967e5ec149b3c1c2c6b20aac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 15:25:09 +0200 Subject: [PATCH 22/61] Fix missing includes --- pylene/include/mln/core/ops.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylene/include/mln/core/ops.hpp b/pylene/include/mln/core/ops.hpp index ba621223..49246d40 100644 --- a/pylene/include/mln/core/ops.hpp +++ b/pylene/include/mln/core/ops.hpp @@ -2,6 +2,8 @@ #include #include +#include +#include /** -- GitLab From 787b94fd95cdd10abdceca122cd561c513743a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 15:25:34 +0200 Subject: [PATCH 23/61] Add experimental image_compare utility --- .../fixtures/ImageCompare/image_compare.hpp | 62 ++++++++ pylene/include/mln/io/imprint.hpp | 139 ++++++++++++++++-- 2 files changed, 187 insertions(+), 14 deletions(-) diff --git a/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp b/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp index 9053edfe..57ecd83d 100644 --- a/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp +++ b/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp @@ -1,8 +1,14 @@ #pragma once #include +#include +#include #include +#include + +#include + #include @@ -17,6 +23,12 @@ namespace fixtures::ImageCompare template bool compare(const mln::Image& f, const mln::Image& g); + namespace experimental + { + template + bool compare(ImageLhs f, ImageRhs g); + } + /******************************************/ /**** Implementation ****/ /******************************************/ @@ -51,8 +63,58 @@ namespace fixtures::ImageCompare } } // namespace impl + + namespace experimental + { + template + bool compare(ImageLhs f, ImageRhs g) + { + static_assert(mln::is_a()); + static_assert(mln::is_a()); + + auto f_dom = f.domain(); + auto g_dom = f.domain(); + if (::ranges::size(f_dom) != ::ranges::size(g_dom)) + return false; + + for (auto&& [f_p, g_p] : mln::ranges::view::zip(f_dom, g_dom)) + if (f_p != g_p) + return false; + + auto zipped_vals = mln::ranges::view::zip(f.new_values(), g.new_values()); + for (auto&& r : mln::ranges::rows(zipped_vals)) + for (auto&& [f_v, g_v] : r) + if (f_v != g_v) + return false; + + return true; + } + + namespace impl + { + template + std::string err_compare_msg(ImageLhs f, ImageRhs g) + { + static_assert(mln::is_a()); + static_assert(mln::is_a()); + + std::stringstream msg; + msg << "The following images differs:\n"; + mln::io::experimental::imprint(f, msg); + msg << " and\n:"; + mln::io::experimental::imprint(g, msg); + return msg.str(); + } + } // namespace impl + } // namespace experimental + + } // namespace fixtures::ImageCompare /// \brief GTest macro for image equality test #define ASSERT_IMAGES_EQ(f, g) \ ASSERT_TRUE(::fixtures::ImageCompare::compare(f, g)) << ::fixtures::ImageCompare::impl::err_compare_msg(f, g) + +#define ASSERT_IMAGES_EQ_EXP(f, g) \ + ASSERT_TRUE(::fixtures::ImageCompare::experimental::compare(f, g)) \ + << ::fixtures::ImageCompare::experimental::impl::err_compare_msg(f, g) diff --git a/pylene/include/mln/io/imprint.hpp b/pylene/include/mln/io/imprint.hpp index 403d854b..a0ac4871 100644 --- a/pylene/include/mln/io/imprint.hpp +++ b/pylene/include/mln/io/imprint.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -23,6 +24,16 @@ namespace mln template void imprint_with_border(const Image& ima, std::ostream& os = std::cout); + + namespace experimental + { + template + void imprint(InputImage ima, std::ostream& os = std::cout); + + template + void imprint_with_border(InputImage ima, std::ostream& os = std::cout); + } // namespace experimental + /******************************************/ /**** Implementation ****/ /******************************************/ @@ -36,7 +47,14 @@ namespace mln for (auto p : domain) { os << '{' << p << ","; - format(os, ima(p)) << "}," << std::endl; + if constexpr (mln::is_a()) + { + format(os, (*const_cast(&ima))(p)) << "}," << std::endl; + } + else + { + format(os, ima(p)) << "}," << std::endl; + } } } @@ -45,10 +63,24 @@ namespace mln imprint(const Image& ima, Domain domain, std::ostream& os) { (void)domain; - mln_foreach (const auto& pix, ima.pixels()) + + if constexpr (mln::is_a()) { - os << '{' << pix.point() << ","; - format(os, pix.val()) << "}," << std::endl; + auto pixels = const_cast(&ima)->new_pixels(); + for (auto&& r : mln::ranges::rows(pixels)) + for (auto&& pix : r) + { + os << '{' << pix.point() << ","; + format(os, pix.val()) << "}," << std::endl; + } + } + else + { + mln_foreach (const auto& pix, ima.pixels()) + { + os << '{' << pix.point() << ","; + format(os, pix.val()) << "}," << std::endl; + } } } @@ -63,8 +95,21 @@ namespace mln int wtext = 0; frmt_max_width frmter; - mln_foreach (V v, ima.values()) - wtext = std::max(wtext, frmter(v)); + + if constexpr (mln::is_a()) + { + auto vals = const_cast(&ima)->new_values(); + for (auto&& r : mln::ranges::rows(vals)) + for (auto&& v : r) + { + wtext = std::max(wtext, frmter(v)); + } + } + else + { + mln_foreach (V v, ima.values()) + wtext = std::max(wtext, frmter(v)); + } os << domain << "(" << typeid(V).name() << ")" << std::endl; os.width(4); @@ -75,7 +120,14 @@ namespace mln for (p[1] = domain.pmin[1]; p[1] < domain.pmax[1]; ++p[1]) { os << std::setw(wtext); - format(os, ima(p)) << " "; + if constexpr (mln::is_a()) + { + format(os, (*const_cast(&ima))(p)) << " "; + } + else + { + format(os, ima(p)) << " "; + } } os << std::endl; } @@ -93,8 +145,21 @@ namespace mln int wtext = 0; frmt_max_width frmter; - mln_foreach (V v, ima.values()) - wtext = std::max(wtext, frmter(v)); + + if constexpr (mln::is_a()) + { + auto vals = const_cast(&ima)->new_values(); + for (auto&& r : mln::ranges::rows(vals)) + for (auto&& v : r) + { + wtext = std::max(wtext, frmter(v)); + } + } + else + { + mln_foreach (V v, ima.values()) + wtext = std::max(wtext, frmter(v)); + } os << domain << "(" << typeid(V).name() << ")" << std::endl; os.width(4); @@ -107,7 +172,14 @@ namespace mln for (p[2] = domain.pmin[2]; p[2] < domain.pmax[2]; ++p[2]) { os << std::setw(wtext); - format(os, ima(p)) << " "; + if constexpr (mln::is_a()) + { + format(os, (*const_cast(&ima))(p)) << " "; + } + else + { + format(os, ima(p)) << " "; + } } os << std::endl; } @@ -127,8 +199,21 @@ namespace mln int wtext = 0; frmt_max_width frmter; - mln_foreach (V v, ima.values()) - wtext = std::max(wtext, frmter(v)); + + if constexpr (mln::is_a()) + { + auto vals = ima.new_values(); + for (auto&& r : mln::ranges::rows(vals)) + for (auto&& v : r) + { + wtext = std::max(wtext, frmter(v)); + } + } + else + { + mln_foreach (V v, ima.values()) + wtext = std::max(wtext, frmter(v)); + } os << domain << "(" << typeid(V).name() << ")" << std::endl; os.width(4); @@ -140,7 +225,14 @@ namespace mln for (p[1] = domain.pmin[1] - border; p[1] < domain.pmax[1] + border; ++p[1]) { os << std::setw(wtext); - format(os, ima.at(p)) << " "; + if constexpr (mln::is_a()) + { + format(os, const_cast(&ima)->at(p)) << " "; + } + else + { + format(os, ima.at(p)) << " "; + } } os << std::endl; } @@ -159,5 +251,24 @@ namespace mln { internal::imprint_with_border(exact(ima), exact(ima).domain(), os); } - } // namespace io + + namespace experimental + { + template + void imprint(InputImage ima, std::ostream& os) + { + static_assert(mln::is_a()); + + internal::imprint(ima, ima.domain(), os); + } + + template + void imprint_with_border(InputImage ima, std::ostream& os) + { + static_assert(mln::is_a()); + + internal::imprint_with_border(ima, ima.domain(), os); + } + } // namespace experimental + } // namespace io } // namespace mln -- GitLab From bf05bfb5ad0563e41da9b73f9b8b19da97853319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 15:25:48 +0200 Subject: [PATCH 24/61] Use image_compare macro to output diff --- tests/core/image/view/maths.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 21aebbd0..51f0e7d3 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include @@ -85,6 +87,5 @@ TEST(View, maths_cbrt) {10, 11, 12, 13, 14}}; auto ima = pow(ref, 3); - // FIXME: - // ASSERT_TRUE(all_of(ref == cbrt(ima))); + ASSERT_IMAGES_EQ_EXP(ref, cbrt(ima)); } -- GitLab From c5ba0d8c942ddb977ddf4f5c6c400c978f69803c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 15:50:04 +0200 Subject: [PATCH 25/61] Fix unit test Disable view::filter::size code --- pylene/include/mln/core/image/view/filter.hpp | 18 ------------------ tests/core/image/view/maths.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/pylene/include/mln/core/image/view/filter.hpp b/pylene/include/mln/core/image/view/filter.hpp index 4524e59b..f55882e0 100644 --- a/pylene/include/mln/core/image/view/filter.hpp +++ b/pylene/include/mln/core/image/view/filter.hpp @@ -58,24 +58,6 @@ namespace mln bool has(point_type p) const { return m_dom.has(p) && m_fun(p); } bool empty() const { return ::ranges::empty(m_rng); } - - auto size() const - { - static std::size_t size = 0; - static bool computed = false; - if (!computed) - { - auto b = begin(); - auto e = end(); - while (b != e) - { - ++size; - ++b; - } - computed = true; - } - return size; - } }; /// \} diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 51f0e7d3..f0fd5147 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -85,7 +86,8 @@ TEST(View, maths_cbrt) image2d ref = {{0, 1, 2, 3, 4}, // {5, 6, 4, 8, 9}, // {10, 11, 12, 13, 14}}; - auto ima = pow(ref, 3); - ASSERT_IMAGES_EQ_EXP(ref, cbrt(ima)); + auto ima = pow(ref, 3); + + ASSERT_TRUE(all_of(ref, view::cast(cbrt(ima)))); } -- GitLab From 8fd5c98f56031c7f14898919ecff394db8f5b2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 16:33:02 +0200 Subject: [PATCH 26/61] WIP --- tests/core/image/view/maths.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index f0fd5147..eaeb5e1d 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -89,5 +89,5 @@ TEST(View, maths_cbrt) auto ima = pow(ref, 3); - ASSERT_TRUE(all_of(ref, view::cast(cbrt(ima)))); + ASSERT_IMAGES_EQ_EXP(ref, view::cast(cbrt(ima))); } -- GitLab From 29fd07e39fdcc29df4f30b7c6780c7f1434e68b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 16:50:52 +0200 Subject: [PATCH 27/61] WIP --- tests/core/image/view/maths.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index eaeb5e1d..900fa6f0 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -90,4 +90,5 @@ TEST(View, maths_cbrt) auto ima = pow(ref, 3); ASSERT_IMAGES_EQ_EXP(ref, view::cast(cbrt(ima))); + ASSERT_TRUE(all_of(ref == view::cast(cbrt(ima)))); } -- GitLab From d4ec9e6a71512f51bc879243a3c9f26f2b9a6dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 3 Apr 2019 18:12:53 +0200 Subject: [PATCH 28/61] Fix unit test --- tests/core/image/view/maths.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 900fa6f0..e23eeaca 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -89,6 +89,5 @@ TEST(View, maths_cbrt) auto ima = pow(ref, 3); - ASSERT_IMAGES_EQ_EXP(ref, view::cast(cbrt(ima))); ASSERT_TRUE(all_of(ref == view::cast(cbrt(ima)))); } -- GitLab From 8eeef8a13902e3a5a516466dc72918e782fab46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Thu, 4 Apr 2019 12:02:40 +0200 Subject: [PATCH 29/61] Add unit tests for l0norm, sum, prod --- pylene/include/mln/core/image/view/maths.hpp | 6 +- tests/core/image/view/maths.cpp | 85 ++++++++++++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/pylene/include/mln/core/image/view/maths.hpp b/pylene/include/mln/core/image/view/maths.hpp index 8b7e10e5..ff9169d7 100644 --- a/pylene/include/mln/core/image/view/maths.hpp +++ b/pylene/include/mln/core/image/view/maths.hpp @@ -18,11 +18,15 @@ namespace mln::view MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sum, functional::sum_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(prod, functional::prod_t<>()); + // TODO: dot, cross, min, max MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l0norm, functional::l0norm_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l1norm, functional::l1norm_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l1dist, functional::l1dist_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l2norm, functional::l2norm_t<>()); + // TODO: l2dist_sqr, l2dist, l1dist, l2norm_sqr MLN_PRIVATE_DEFINE_UNARY_OPERATOR(linfnorm, functional::linfnorm_t<>()); - MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l1dist, functional::l1dist_t<>()); + // TODO: lpnorm + } // namespace maths } // namespace mln::view diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index e23eeaca..9d7db3a8 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -91,3 +92,87 @@ TEST(View, maths_cbrt) ASSERT_TRUE(all_of(ref == view::cast(cbrt(ima)))); } + +TEST(View, maths_sum) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == sum(ima))); + + + image2d ima2 = {{1, -2, 3}, // + {4, -5, 6}, // + {7, -8, 9}}; + + image2d ref2 = {2, 5, 8}; + + ASSERT_IMAGES_EQ_EXP(ref2, sum(ima2)); + ASSERT_TRUE(all_of(ref2 == sum(ima2))); +} + +TEST(View, maths_prod) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == prod(ima))); + + + image2d ima2 = {{1, -2, 3}, // + {4, -5, 6}, // + {7, -8, 9}}; + + image2d ref2 = {{-6}, {-120}, {-504}}; + + ASSERT_IMAGES_EQ_EXP(ref2, prod(ima2)); + ASSERT_TRUE(all_of(ref2 == prod(ima2))); +} + +TEST(View, maths_l0norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == l0norm(ima))); + + + image2d ima2 = {{1, -2, 3}, // + {4, -5, 6}, // + {7, -8, 9}}; + + image2d ref2 = {1, 4, 7}; + + ASSERT_IMAGES_EQ_EXP(ref2, l0norm(ima2)); + ASSERT_TRUE(all_of(ref2 == l0norm(ima2))); +} -- GitLab From aab0d9940c7380cc1684cd033bacda40b182db90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Thu, 4 Apr 2019 12:28:12 +0200 Subject: [PATCH 30/61] Fix images' and refs' values --- tests/core/image/view/maths.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 9d7db3a8..911a9938 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -111,11 +111,13 @@ TEST(View, maths_sum) ASSERT_TRUE(all_of(ref == sum(ima))); - image2d ima2 = {{1, -2, 3}, // - {4, -5, 6}, // - {7, -8, 9}}; + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - image2d ref2 = {2, 5, 8}; + image2d ref2 = {{6, 15, 24}, // + {6, 15, 24}, // + {6, 15, 24}}; ASSERT_IMAGES_EQ_EXP(ref2, sum(ima2)); ASSERT_TRUE(all_of(ref2 == sum(ima2))); @@ -139,11 +141,13 @@ TEST(View, maths_prod) ASSERT_TRUE(all_of(ref == prod(ima))); - image2d ima2 = {{1, -2, 3}, // - {4, -5, 6}, // - {7, -8, 9}}; + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - image2d ref2 = {{-6}, {-120}, {-504}}; + image2d ref2 = {{6, 120, 504}, // + {6, 120, 504}, // + {6, 120, 504}}; ASSERT_IMAGES_EQ_EXP(ref2, prod(ima2)); ASSERT_TRUE(all_of(ref2 == prod(ima2))); @@ -167,11 +171,13 @@ TEST(View, maths_l0norm) ASSERT_TRUE(all_of(ref == l0norm(ima))); - image2d ima2 = {{1, -2, 3}, // - {4, -5, 6}, // - {7, -8, 9}}; + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - image2d ref2 = {1, 4, 7}; + image2d ref2 = {{1, 4, 7}, // + {1, 4, 7}, // + {1, 4, 7}}; ASSERT_IMAGES_EQ_EXP(ref2, l0norm(ima2)); ASSERT_TRUE(all_of(ref2 == l0norm(ima2))); -- GitLab From c0dcae8c39d4d818a823521b91146561d98215e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Thu, 4 Apr 2019 16:49:39 +0200 Subject: [PATCH 31/61] Remove debug check --- tests/core/image/view/maths.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 911a9938..14a7813c 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -119,7 +119,6 @@ TEST(View, maths_sum) {6, 15, 24}, // {6, 15, 24}}; - ASSERT_IMAGES_EQ_EXP(ref2, sum(ima2)); ASSERT_TRUE(all_of(ref2 == sum(ima2))); } @@ -149,7 +148,6 @@ TEST(View, maths_prod) {6, 120, 504}, // {6, 120, 504}}; - ASSERT_IMAGES_EQ_EXP(ref2, prod(ima2)); ASSERT_TRUE(all_of(ref2 == prod(ima2))); } @@ -179,6 +177,5 @@ TEST(View, maths_l0norm) {1, 4, 7}, // {1, 4, 7}}; - ASSERT_IMAGES_EQ_EXP(ref2, l0norm(ima2)); ASSERT_TRUE(all_of(ref2 == l0norm(ima2))); } -- GitLab From dcb8bbb1b598568c758587605eec46151cbe6796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 5 Apr 2019 11:08:53 +0200 Subject: [PATCH 32/61] Add l1norm, l2norm unit test --- pylene/include/mln/core/image/view/maths.hpp | 2 +- tests/core/image/view/maths.cpp | 60 ++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/pylene/include/mln/core/image/view/maths.hpp b/pylene/include/mln/core/image/view/maths.hpp index ff9169d7..c6803885 100644 --- a/pylene/include/mln/core/image/view/maths.hpp +++ b/pylene/include/mln/core/image/view/maths.hpp @@ -23,7 +23,7 @@ namespace mln::view MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l1norm, functional::l1norm_t<>()); MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l1dist, functional::l1dist_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l2norm, functional::l2norm_t<>()); - // TODO: l2dist_sqr, l2dist, l1dist, l2norm_sqr + // TODO: l2dist_sqr, l2dist, l2norm_sqr MLN_PRIVATE_DEFINE_UNARY_OPERATOR(linfnorm, functional::linfnorm_t<>()); // TODO: lpnorm diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 14a7813c..c84bc2d4 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -179,3 +179,63 @@ TEST(View, maths_l0norm) ASSERT_TRUE(all_of(ref2 == l0norm(ima2))); } + +TEST(View, maths_l1norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == l1norm(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{6, 15, 24}, // + {6, 15, 24}, // + {6, 15, 24}}; + + ASSERT_IMAGES_EQ_EXP(ref2, l1norm(ima2)); + ASSERT_TRUE(all_of(ref2 == l1norm(ima2))); +} + +TEST(View, maths_l2norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == l2norm(ima))); + + + image2d ima2 = {{{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}}; + + image2d ref2 = {{3, 6, 9}, // + {3, 6, 9}, // + {3, 6, 9}}; + + ASSERT_IMAGES_EQ_EXP(ref2, l2norm(ima2)); + ASSERT_TRUE(all_of(ref2 == l2norm(ima2))); +} -- GitLab From a71958d3cd22a2f1880f361b7443397fc477b8a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 5 Apr 2019 11:21:19 +0200 Subject: [PATCH 33/61] Fix image_compare not to rely on ::ranges::size anymore --- .../fixtures/ImageCompare/image_compare.hpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp b/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp index 57ecd83d..398cc26b 100644 --- a/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp +++ b/fixtures/ImageCompare/include/fixtures/ImageCompare/image_compare.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include @@ -74,13 +74,18 @@ namespace fixtures::ImageCompare auto f_dom = f.domain(); auto g_dom = f.domain(); - if (::ranges::size(f_dom) != ::ranges::size(g_dom)) - return false; - for (auto&& [f_p, g_p] : mln::ranges::view::zip(f_dom, g_dom)) - if (f_p != g_p) + auto f_dom_b = ::ranges::begin(f_dom); + auto g_dom_b = ::ranges::begin(g_dom); + auto f_dom_e = ::ranges::end(f_dom); + auto g_dom_e = ::ranges::end(g_dom); + for (; (f_dom_b != f_dom_e) || (g_dom_b != g_dom_e); ++f_dom_b, ++g_dom_b) + if (*f_dom_b != *g_dom_b) return false; + if ((f_dom_b != f_dom_e) || (g_dom_b != g_dom_e)) + return false; + auto zipped_vals = mln::ranges::view::zip(f.new_values(), g.new_values()); for (auto&& r : mln::ranges::rows(zipped_vals)) for (auto&& [f_v, g_v] : r) -- GitLab From 7c064f6f66e4572ec3fc3a1b138963480b5cc7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Fri, 5 Apr 2019 11:59:16 +0200 Subject: [PATCH 34/61] Add linfnorm --- tests/core/image/view/maths.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index c84bc2d4..6f264056 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -206,7 +206,6 @@ TEST(View, maths_l1norm) {6, 15, 24}, // {6, 15, 24}}; - ASSERT_IMAGES_EQ_EXP(ref2, l1norm(ima2)); ASSERT_TRUE(all_of(ref2 == l1norm(ima2))); } @@ -236,6 +235,35 @@ TEST(View, maths_l2norm) {3, 6, 9}, // {3, 6, 9}}; - ASSERT_IMAGES_EQ_EXP(ref2, l2norm(ima2)); ASSERT_TRUE(all_of(ref2 == l2norm(ima2))); } + +TEST(View, maths_linfnorm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == linfnorm(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{3, 6, 9}, // + {3, 6, 9}, // + {3, 6, 9}}; + + ASSERT_IMAGES_EQ_EXP(ref2, linfnorm(ima2)); + ASSERT_TRUE(all_of(ref2 == linfnorm(ima2))); +} -- GitLab From df75d7a5163ac7cbb75255dc5b375b3cf4f47d12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 9 Apr 2019 11:31:26 +0200 Subject: [PATCH 35/61] Add lpnorm/lpdist operator view for images Cleanup vec_math_ops Cleanup math_ops macros Add missing maths operators Write unit tests Add 7-dimension cross product --- apps/attributes/gradient_magnitude.hpp | 2 +- apps/attributes/meaningfullness.hpp | 4 +- .../accu/accumulators/moment_of_inertia.hpp | 2 +- .../mln/accu/accumulators/variance.hpp | 2 +- pylene/include/mln/core/colors.hpp | 12 +- pylene/include/mln/core/functional_ops.hpp | 127 +++++ pylene/include/mln/core/image/image.hpp | 2 +- ...image_math_ops.hpp => image_maths_ops.hpp} | 2 +- ...gen_macros.hpp => def_gen_code_macros.hpp} | 0 ...n_macros.hpp => undef_gen_code_macros.hpp} | 0 pylene/include/mln/core/image/view/maths.hpp | 62 ++- .../include/mln/core/image/view/operators.hpp | 4 +- pylene/include/mln/core/math_ops.hpp | 475 ------------------ .../def_functional_ops_gen_code_macros.hpp | 43 ++ .../private/def_maths_ops_gen_code_macros.hpp | 12 + pylene/include/mln/core/private/maths_ops.hpp | 388 ++++++++++++++ .../undef_functional_ops_gen_code_macros.hpp | 3 + .../undef_maths_ops_gen_code_macros.hpp | 5 + pylene/include/mln/core/vec.hpp | 2 +- .../core/vec/private/def_gen_code_macros.hpp | 26 + .../vec/private/undef_gen_code_macros.hpp | 7 + pylene/include/mln/core/vec/vec_math_ops.hpp | 276 ---------- pylene/include/mln/core/vec/vec_maths_ops.hpp | 296 +++++++++++ .../mln/morpho/structural/gradient.hpp | 2 +- tests/core/image/view/maths.cpp | 433 +++++++++++++++- tests/core/vec/vec_math_ops.cpp | 2 +- 26 files changed, 1403 insertions(+), 786 deletions(-) create mode 100644 pylene/include/mln/core/functional_ops.hpp rename pylene/include/mln/core/image/{image_math_ops.hpp => image_maths_ops.hpp} (96%) rename pylene/include/mln/core/image/private/{def_gen_macros.hpp => def_gen_code_macros.hpp} (100%) rename pylene/include/mln/core/image/private/{undef_gen_macros.hpp => undef_gen_code_macros.hpp} (100%) delete mode 100644 pylene/include/mln/core/math_ops.hpp create mode 100644 pylene/include/mln/core/private/def_functional_ops_gen_code_macros.hpp create mode 100644 pylene/include/mln/core/private/def_maths_ops_gen_code_macros.hpp create mode 100644 pylene/include/mln/core/private/maths_ops.hpp create mode 100644 pylene/include/mln/core/private/undef_functional_ops_gen_code_macros.hpp create mode 100644 pylene/include/mln/core/private/undef_maths_ops_gen_code_macros.hpp create mode 100644 pylene/include/mln/core/vec/private/def_gen_code_macros.hpp create mode 100644 pylene/include/mln/core/vec/private/undef_gen_code_macros.hpp delete mode 100644 pylene/include/mln/core/vec/vec_math_ops.hpp create mode 100644 pylene/include/mln/core/vec/vec_maths_ops.hpp diff --git a/apps/attributes/gradient_magnitude.hpp b/apps/attributes/gradient_magnitude.hpp index 35baa969..3b5953e9 100644 --- a/apps/attributes/gradient_magnitude.hpp +++ b/apps/attributes/gradient_magnitude.hpp @@ -3,8 +3,8 @@ #include #include +#include #include -#include #include diff --git a/apps/attributes/meaningfullness.hpp b/apps/attributes/meaningfullness.hpp index 41d47976..5e0793a9 100644 --- a/apps/attributes/meaningfullness.hpp +++ b/apps/attributes/meaningfullness.hpp @@ -4,11 +4,11 @@ #include #include +#include #include -#include #include #include -#include +#include #include diff --git a/pylene/include/mln/accu/accumulators/moment_of_inertia.hpp b/pylene/include/mln/accu/accumulators/moment_of_inertia.hpp index 6543f54a..f1937833 100644 --- a/pylene/include/mln/accu/accumulators/moment_of_inertia.hpp +++ b/pylene/include/mln/accu/accumulators/moment_of_inertia.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/pylene/include/mln/accu/accumulators/variance.hpp b/pylene/include/mln/accu/accumulators/variance.hpp index c6b0e29c..554e3e57 100644 --- a/pylene/include/mln/accu/accumulators/variance.hpp +++ b/pylene/include/mln/accu/accumulators/variance.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include diff --git a/pylene/include/mln/core/colors.hpp b/pylene/include/mln/core/colors.hpp index 8dcf0d0a..36791257 100644 --- a/pylene/include/mln/core/colors.hpp +++ b/pylene/include/mln/core/colors.hpp @@ -44,14 +44,18 @@ namespace mln template using rgb = internal::vec_base; - typedef rgb rgb8; - typedef rgb rgb16; + using rgb8 = rgb; + using signed_rgb8 = rgb; + using rgb16 = rgb; + using signed_rgb16 = rgb; template using bgr = internal::vec_base; - typedef bgr bgr8; - typedef bgr bgr16; + using bgr8 = bgr; + using signed_bgr8 = bgr; + using bgr16 = bgr; + using signed_bgr16 = bgr; template internal::transformed_image channel(Image&& f, int k) diff --git a/pylene/include/mln/core/functional_ops.hpp b/pylene/include/mln/core/functional_ops.hpp new file mode 100644 index 00000000..0871530e --- /dev/null +++ b/pylene/include/mln/core/functional_ops.hpp @@ -0,0 +1,127 @@ +#pragma once + +#include +#include + +#include + + +#include + +namespace mln +{ + namespace functional + { + template + struct sqrt_t; + template + struct cbrt_t; + template + struct pow_t; + template + struct sqr_t; + template + struct abs_t; + template + struct sum_t; + template + struct prod_t; + template + struct dot_t; + template + struct cross_t; + template + struct minimum_t; + template + struct maximum_t; + + template + struct l0norm_t; + template + struct l1norm_t; + template + struct l2norm_t; + template + struct l2norm_sqr_t; + template + struct linfnorm_t; + template + struct lpnorm_t; + + template + struct l0dist_t; + template + struct l1dist_t; + template + struct l2dist_t; + template + struct lpdist_t; + template + struct l2dist_sqr_t; + template + struct linfdist_t; + }; // namespace functional + + + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(sqrt); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(cbrt); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(pow); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(sqr); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(abs); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(sum); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(prod); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(dot); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(cross); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(maximum); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(minimum); + + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(l0norm); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(l1norm); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(l2norm); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(l2norm_sqr); + MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(linfnorm); + namespace functional + { + template + struct lpnorm_t + { + typedef decltype(lpnorm

(std::declval())) result_type; + auto operator()(const T& x) const -> decltype(lpnorm

(x)) { return lpnorm

(x); } + }; + template + struct lpnorm_t + { + template + auto operator()(const T& x) const -> decltype(lpnorm

(x)) + { + return lpnorm

(x); + } + }; + } // namespace functional + + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(l0dist); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(l1dist); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(l2dist); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(l2dist_sqr); + MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(linfdist); + namespace functional + { + template + struct lpdist_t + { + typedef decltype(lpdist

(std::declval(), std::declval())) result_type; + auto operator()(const T1& x, const T2& y) const -> decltype(lpdist

(x, y)) { return lpdist

(x, y); } + }; + template + struct lpdist_t + { + template + auto operator()(const T1& x, const T2& y) const -> decltype(lpdist

(x, y)) + { + return lpdist

(x, y); + } + }; + } // namespace functional +} // namespace mln + +#include diff --git a/pylene/include/mln/core/image/image.hpp b/pylene/include/mln/core/image/image.hpp index 6f732690..ba5532b6 100644 --- a/pylene/include/mln/core/image/image.hpp +++ b/pylene/include/mln/core/image/image.hpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/pylene/include/mln/core/image/image_math_ops.hpp b/pylene/include/mln/core/image/image_maths_ops.hpp similarity index 96% rename from pylene/include/mln/core/image/image_math_ops.hpp rename to pylene/include/mln/core/image/image_maths_ops.hpp index 27f2015a..12a9f643 100644 --- a/pylene/include/mln/core/image/image_math_ops.hpp +++ b/pylene/include/mln/core/image/image_maths_ops.hpp @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include namespace mln { diff --git a/pylene/include/mln/core/image/private/def_gen_macros.hpp b/pylene/include/mln/core/image/private/def_gen_code_macros.hpp similarity index 100% rename from pylene/include/mln/core/image/private/def_gen_macros.hpp rename to pylene/include/mln/core/image/private/def_gen_code_macros.hpp diff --git a/pylene/include/mln/core/image/private/undef_gen_macros.hpp b/pylene/include/mln/core/image/private/undef_gen_code_macros.hpp similarity index 100% rename from pylene/include/mln/core/image/private/undef_gen_macros.hpp rename to pylene/include/mln/core/image/private/undef_gen_code_macros.hpp diff --git a/pylene/include/mln/core/image/view/maths.hpp b/pylene/include/mln/core/image/view/maths.hpp index c6803885..99ac308b 100644 --- a/pylene/include/mln/core/image/view/maths.hpp +++ b/pylene/include/mln/core/image/view/maths.hpp @@ -1,34 +1,78 @@ #pragma once -#include +#include -#include +#include namespace mln::view { namespace maths { - MLN_PRIVATE_DEFINE_UNARY_OPERATOR(abs, functional::abs_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sqr, functional::sqr_t<>()); MLN_PRIVATE_DEFINE_BINARY_OPERATOR(pow, functional::pow_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sqrt, functional::sqrt_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(cbrt, functional::cbrt_t<>()); - MLN_PRIVATE_DEFINE_UNARY_OPERATOR(sum, functional::sum_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(prod, functional::prod_t<>()); - // TODO: dot, cross, min, max + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(dot, functional::dot_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(cross, functional::cross_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(min, functional::minimum_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(max, functional::maximum_t<>()); + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l0norm, functional::l0norm_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l1norm, functional::l1norm_t<>()); - MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l1dist, functional::l1dist_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l2norm, functional::l2norm_t<>()); - // TODO: l2dist_sqr, l2dist, l2norm_sqr + MLN_PRIVATE_DEFINE_UNARY_OPERATOR(l2norm_sqr, functional::l2norm_sqr_t<>()); MLN_PRIVATE_DEFINE_UNARY_OPERATOR(linfnorm, functional::linfnorm_t<>()); - // TODO: lpnorm + template ::value>> + auto lpnorm(const I& ima) + { + return ::mln::view::transform(static_cast(ima), functional::lpnorm_t

{}); + } + + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l0dist, functional::l0dist_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l1dist, functional::l1dist_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l2dist, functional::l2dist_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(l2dist_sqr, functional::l2dist_sqr_t<>()); + MLN_PRIVATE_DEFINE_BINARY_OPERATOR(linfdist, functional::linfdist_t<>()); + namespace impl + { + template + auto lpdist(const ::mln::experimental::Image& ima1, const ::mln::experimental::Image& ima2) + { + return ::mln::view::transform(static_cast(ima1), static_cast(ima2), + functional::lpdist_t

{}); + } + + template ::value>> + auto lpdist(const ::mln::experimental::Image& ima1, Scalar s) + { + auto g = [f_ = functional::lpdist_t

{}, s](auto&& arg) { return f_(arg, s); }; + return ::mln::view::transform(static_cast(ima1), g); + } + + template ::value>> + auto lpdist(Scalar s, const ::mln::experimental::Image& ima2) + { + auto g = [f_ = functional::lpdist_t

{}, s](auto&& arg) { return f_(s, arg); }; + return ::mln::view::transform(static_cast(ima2), g); + } + } /* namespace impl */ + /* This overload is there to be a best match wrt old API impl */ + template ::value || + ::mln::is_a::value)>> + auto lpdist(const A& lhs, const B& rhs) + { + return impl::lpdist

(lhs, rhs); + } } // namespace maths } // namespace mln::view -#include +#include diff --git a/pylene/include/mln/core/image/view/operators.hpp b/pylene/include/mln/core/image/view/operators.hpp index 089c77d4..3948db79 100644 --- a/pylene/include/mln/core/image/view/operators.hpp +++ b/pylene/include/mln/core/image/view/operators.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace mln::view { @@ -126,6 +126,6 @@ namespace mln::view std::move(iffalse)); } -#include +#include } // namespace mln::view diff --git a/pylene/include/mln/core/math_ops.hpp b/pylene/include/mln/core/math_ops.hpp deleted file mode 100644 index e3e096cd..00000000 --- a/pylene/include/mln/core/math_ops.hpp +++ /dev/null @@ -1,475 +0,0 @@ -#pragma once - -/** - * \file - * \brief Define fundamental mathematical and statistical operators - * - */ - -#include -#include -#include - - -namespace mln -{ - /* Element wise operators */ - int sqr(int x); - long sqr(long n); - long long sqr(long long n); - unsigned int sqr(unsigned int x); - unsigned long sqr(unsigned long n); - unsigned long long sqr(unsigned long long n); - float sqr(float x); - double sqr(double x); - long double sqr(long double x); - - int abs(int x); - long abs(long n); - long long abs(long long n); - unsigned int abs(unsigned int x); - unsigned long abs(unsigned long n); - unsigned long long abs(unsigned long long n); - float abs(float x); - double abs(double x); - long double abs(long double x); - - using std::cbrt; - using std::pow; - using std::sqrt; - - /* Reduction operators */ - int sum(int x); - long sum(long n); - long long sum(long long n); - unsigned int sum(unsigned int x); - unsigned long sum(unsigned long n); - unsigned long long sum(unsigned long long n); - float sum(float x); - double sum(double x); - long double sum(long double x); - - int prod(int x); - long prod(long n); - long long prod(long long n); - unsigned int prod(unsigned int x); - unsigned long prod(unsigned long n); - unsigned long long prod(unsigned long long n); - float prod(float x); - double prod(double x); - long double prod(long double x); - - int minimum(int x); - long minimum(long n); - long long minimum(long long n); - unsigned int minimum(unsigned int x); - unsigned long minimum(unsigned long n); - unsigned long long minimum(unsigned long long n); - float minimum(float x); - double minimum(double x); - long double minimum(long double x); - - int maximum(int x); - long maximum(long n); - long long maximum(long long n); - unsigned int maximum(unsigned int x); - unsigned long maximum(unsigned long n); - unsigned long long maximum(unsigned long long n); - float maximum(float x); - double maximum(double x); - long double maximum(long double x); - - int l0norm(int x); - long l0norm(long n); - long long l0norm(long long n); - unsigned int l0norm(unsigned int x); - unsigned long l0norm(unsigned long n); - unsigned long long l0norm(unsigned long long n); - float l0norm(float x); - double l0norm(double x); - long double l0norm(long double x); - - int l1norm(int x); - long l1norm(long n); - long long l1norm(long long n); - unsigned int l1norm(unsigned int x); - unsigned long l1norm(unsigned long n); - unsigned long long l1norm(unsigned long long n); - float l1norm(float x); - double l1norm(double x); - long double l1norm(long double x); - - int l2norm(int x); - long l2norm(long n); - long long l2norm(long long n); - unsigned int l2norm(unsigned int x); - unsigned long l2norm(unsigned long n); - unsigned long long l2norm(unsigned long long n); - float l2norm(float x); - double l2norm(double x); - long double l2norm(long double x); - - int l2dist(int x, int y); - long l2dist(long x, long y); - long long l2dist(long long x, long long y); - unsigned int l2dist(unsigned int x, unsigned int y); - unsigned long l2dist(unsigned long x, unsigned long y); - unsigned long long l2dist(unsigned long long x, unsigned long long y); - float l2dist(float x, float y); - double l2dist(double x, double y); - long double l2dist(long double x, long double y); - - int l1dist(int x, int y); - long l1dist(long x, long y); - long long l1dist(long long x, long long y); - unsigned int l1dist(unsigned int x, unsigned int y); - unsigned long l1dist(unsigned long x, unsigned long y); - unsigned long long l1dist(unsigned long long x, unsigned long long y); - float l1dist(float x, float y); - double l1dist(double x, double y); - long double l1dist(long double x, long double y); - - int l2norm_sqr(int x); - long l2norm_sqr(long n); - long long l2norm_sqr(long long n); - unsigned int l2norm_sqr(unsigned int x); - unsigned long l2norm_sqr(unsigned long n); - unsigned long long l2norm_sqr(unsigned long long n); - float l2norm_sqr(float x); - double l2norm_sqr(double x); - long double l2norm_sqr(long double x); - - int l2dist_sqr(int x, int y); - long l2dist_sqr(long x, long y); - long long l2dist_sqr(long long x, long long y); - unsigned int l2dist_sqr(unsigned int x, unsigned int y); - unsigned long l2dist_sqr(unsigned long x, unsigned long y); - unsigned long long l2dist_sqr(unsigned long long x, unsigned long long y); - float l2dist_sqr(float x, float y); - double l2dist_sqr(double x, double y); - long double l2dist_sqr(long double x, long double y); - - int linfnorm(int x); - long linfnorm(long n); - long long linfnorm(long long n); - unsigned int linfnorm(unsigned int x); - unsigned long linfnorm(unsigned long n); - unsigned long long linfnorm(unsigned long long n); - float linfnorm(float x); - double linfnorm(double x); - long double linfnorm(long double x); - - template - int lpnorm(int x); - template - long lpnorm(long x); - template - long long lpnorm(long long x); - template - unsigned int lpnorm(unsigned int x); - template - unsigned long lpnorm(unsigned long n); - template - unsigned long long lpnorm(unsigned long long n); - template - float lpnorm(float x); - template - double lpnorm(double x); - template - long double lpnorm(long double x); - - namespace functional - { - template - struct sqrt_t; - template - struct cbrt_t; - template - struct pow_t; - template - struct sqr_t; - template - struct abs_t; - - template - struct sum_t; - template - struct prod_t; - template - struct minimum_t; - template - struct maximum_t; - template - struct l0norm_t; - template - struct l1norm_t; - template - struct l2norm_t; - template - struct l2norm_sqr_t; - template - struct linfnorm_t; - template - struct lpnorm_t; - - template - struct l0dist_t; - template - struct l1dist_t; - template - struct l2dist_t; - template - struct linfdist_t; - }; // namespace functional - - /********************************/ - /*** Implementation **/ - /********************************/ - -#define MLN_GEN_CODE(FUN, TYPE, OP) \ - inline TYPE FUN(TYPE x) { return OP; } - -#define MLN_GEN_BINARY_CODE(FUN, TYPE, OP) \ - inline TYPE FUN(TYPE x, TYPE y) { return OP; } - -#define MLN_GEN_CODE_2(TEMPLATE, FUN, TYPE, OP) \ - TEMPLATE inline TYPE FUN(TYPE x) { return OP; } - -#define MLN_FUNCTIONAL_GEN_UNARY_CODE(FUN) \ - namespace functional \ - { \ - using mln::FUN; \ - template \ - struct FUN##_t \ - { \ - typedef decltype(FUN(std::declval())) result_type; \ - auto operator()(const T& x) const -> decltype(FUN(x)) { return FUN(x); } \ - }; \ - template <> \ - struct FUN##_t \ - { \ - template \ - auto operator()(const T& x) const -> decltype(FUN(x)) \ - { \ - return FUN(x); \ - } \ - }; \ - } - -#define MLN_FUNCTIONAL_GEN_BINARY_CODE(FUN) \ - namespace functional \ - { \ - using mln::FUN; \ - template \ - struct FUN##_t \ - { \ - typedef decltype(FUN(std::declval(), std::declval())) result_type; \ - auto operator()(const T1& x, const T2& y) const -> decltype(FUN(x, y)) { return FUN(x, y); } \ - }; \ - template <> \ - struct FUN##_t \ - { \ - template \ - auto operator()(const T1& x, const T2& y) const -> decltype(FUN(x, y)) \ - { \ - return FUN(x, y); \ - } \ - }; \ - } - -#define MLN_FUNCTIONAL_GEN_CODE_2(TTYPE, TNAME, FUN) \ - namespace functional \ - { \ - template \ - struct FUN##_t \ - { \ - typedef decltype(FUN(std::declval())) result_type; \ - auto operator()(const T& x) const -> decltype(FUN(x)) { return FUN(x); } \ - }; \ - template \ - struct FUN##_t \ - { \ - template \ - auto operator()(const T& x) const -> decltype(FUN(x)) \ - { \ - return FUN(x); \ - } \ - }; \ - } - - MLN_FUNCTIONAL_GEN_UNARY_CODE(sqrt); - MLN_FUNCTIONAL_GEN_UNARY_CODE(cbrt); - MLN_FUNCTIONAL_GEN_BINARY_CODE(pow); - - MLN_GEN_CODE(sqr, int, x* x); - MLN_GEN_CODE(sqr, long, x* x); - MLN_GEN_CODE(sqr, long long, x* x); - MLN_GEN_CODE(sqr, unsigned int, x* x); - MLN_GEN_CODE(sqr, unsigned long, x* x); - MLN_GEN_CODE(sqr, unsigned long long, x* x); - MLN_GEN_CODE(sqr, float, x* x); - MLN_GEN_CODE(sqr, double, x* x); - MLN_GEN_CODE(sqr, long double, x* x); - MLN_FUNCTIONAL_GEN_UNARY_CODE(sqr); - - MLN_GEN_CODE(abs, int, std::abs(x)); - MLN_GEN_CODE(abs, long, std::abs(x)); - MLN_GEN_CODE(abs, long long, std::abs(x)); - MLN_GEN_CODE(abs, unsigned int, x); - MLN_GEN_CODE(abs, unsigned long, x); - MLN_GEN_CODE(abs, unsigned long long, x); - MLN_GEN_CODE(abs, float, std::abs(x)); - MLN_GEN_CODE(abs, double, std::abs(x)); - MLN_GEN_CODE(abs, long double, std::abs(x)); - MLN_FUNCTIONAL_GEN_UNARY_CODE(abs); - - MLN_GEN_CODE(l0norm, int, std::abs(x)); - MLN_GEN_CODE(l0norm, long, std::abs(x)); - MLN_GEN_CODE(l0norm, long long, std::abs(x)); - MLN_GEN_CODE(l0norm, unsigned int, x); - MLN_GEN_CODE(l0norm, unsigned long, x); - MLN_GEN_CODE(l0norm, unsigned long long, x); - MLN_GEN_CODE(l0norm, float, std::abs(x)); - MLN_GEN_CODE(l0norm, double, std::abs(x)); - MLN_GEN_CODE(l0norm, long double, std::abs(x)); - MLN_FUNCTIONAL_GEN_UNARY_CODE(l0norm); - - MLN_GEN_CODE(l1norm, int, std::abs(x)); - MLN_GEN_CODE(l1norm, long, std::abs(x)); - MLN_GEN_CODE(l1norm, long long, std::abs(x)); - MLN_GEN_CODE(l1norm, unsigned int, x); - MLN_GEN_CODE(l1norm, unsigned long, x); - MLN_GEN_CODE(l1norm, unsigned long long, x); - MLN_GEN_CODE(l1norm, float, std::abs(x)); - MLN_GEN_CODE(l1norm, double, std::abs(x)); - MLN_GEN_CODE(l1norm, long double, std::abs(x)); - MLN_FUNCTIONAL_GEN_UNARY_CODE(l1norm); - - MLN_GEN_CODE(l2norm, int, std::abs(x)); - MLN_GEN_CODE(l2norm, long, std::abs(x)); - MLN_GEN_CODE(l2norm, long long, std::abs(x)); - MLN_GEN_CODE(l2norm, unsigned int, x); - MLN_GEN_CODE(l2norm, unsigned long, x); - MLN_GEN_CODE(l2norm, unsigned long long, x); - MLN_GEN_CODE(l2norm, float, std::abs(x)); - MLN_GEN_CODE(l2norm, double, std::abs(x)); - MLN_GEN_CODE(l2norm, long double, std::abs(x)); - MLN_FUNCTIONAL_GEN_UNARY_CODE(l2norm); - - MLN_GEN_BINARY_CODE(l2dist, int, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, long, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, long long, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, unsigned int, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, unsigned long, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, unsigned long long, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, float, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, double, abs(x - y)); - MLN_GEN_BINARY_CODE(l2dist, long double, abs(x - y)); - MLN_FUNCTIONAL_GEN_BINARY_CODE(l2dist); - - MLN_GEN_BINARY_CODE(l1dist, int, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, long, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, long long, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, unsigned int, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, unsigned long, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, unsigned long long, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, float, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, double, abs(x - y)); - MLN_GEN_BINARY_CODE(l1dist, long double, abs(x - y)); - MLN_FUNCTIONAL_GEN_BINARY_CODE(l1dist); - - MLN_GEN_CODE(l2norm_sqr, int, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, long, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, long long, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, unsigned int, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, unsigned long, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, unsigned long long, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, float, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, double, sqr(x)); - MLN_GEN_CODE(l2norm_sqr, long double, sqr(x)); - MLN_FUNCTIONAL_GEN_UNARY_CODE(l2norm_sqr); - - MLN_GEN_BINARY_CODE(l2dist_sqr, int, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, long, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, long long, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, unsigned int, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, unsigned long, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, unsigned long long, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, float, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, double, sqr(x - y)); - MLN_GEN_BINARY_CODE(l2dist_sqr, long double, sqr(x - y)); - MLN_FUNCTIONAL_GEN_BINARY_CODE(l2dist_sqr); - - MLN_GEN_CODE(linfnorm, int, std::abs(x)); - MLN_GEN_CODE(linfnorm, long, std::abs(x)); - MLN_GEN_CODE(linfnorm, long long, std::abs(x)); - MLN_GEN_CODE(linfnorm, unsigned int, x); - MLN_GEN_CODE(linfnorm, unsigned long, x); - MLN_GEN_CODE(linfnorm, unsigned long long, x); - MLN_GEN_CODE(linfnorm, float, std::abs(x)); - MLN_GEN_CODE(linfnorm, double, std::abs(x)); - MLN_GEN_CODE(linfnorm, long double, std::abs(x)); - MLN_FUNCTIONAL_GEN_UNARY_CODE(linfnorm); - - MLN_GEN_CODE_2(template , lpnorm, int, std::abs(x)); - MLN_GEN_CODE_2(template , lpnorm, long, std::abs(x)); - MLN_GEN_CODE_2(template , lpnorm, long long, std::abs(x)); - MLN_GEN_CODE_2(template , lpnorm, unsigned int, x); - MLN_GEN_CODE_2(template , lpnorm, unsigned long, x); - MLN_GEN_CODE_2(template , lpnorm, unsigned long long, x); - MLN_GEN_CODE_2(template , lpnorm, float, std::abs(x)); - MLN_GEN_CODE_2(template , lpnorm, double, std::abs(x)); - MLN_GEN_CODE_2(template , lpnorm, long double, std::abs(x)); - MLN_FUNCTIONAL_GEN_CODE_2(unsigned, p, lpnorm); - - MLN_GEN_CODE(maximum, int, x); - MLN_GEN_CODE(maximum, long, x); - MLN_GEN_CODE(maximum, long long, x); - MLN_GEN_CODE(maximum, unsigned int, x); - MLN_GEN_CODE(maximum, unsigned long, x); - MLN_GEN_CODE(maximum, unsigned long long, x); - MLN_GEN_CODE(maximum, float, x); - MLN_GEN_CODE(maximum, double, x); - MLN_GEN_CODE(maximum, long double, x); - MLN_FUNCTIONAL_GEN_UNARY_CODE(maximum); - - MLN_GEN_CODE(minimum, int, x); - MLN_GEN_CODE(minimum, long, x); - MLN_GEN_CODE(minimum, long long, x); - MLN_GEN_CODE(minimum, unsigned int, x); - MLN_GEN_CODE(minimum, unsigned long, x); - MLN_GEN_CODE(minimum, unsigned long long, x); - MLN_GEN_CODE(minimum, float, x); - MLN_GEN_CODE(minimum, double, x); - MLN_GEN_CODE(minimum, long double, x); - MLN_FUNCTIONAL_GEN_UNARY_CODE(minimum); - - MLN_GEN_CODE(sum, int, x); - MLN_GEN_CODE(sum, long, x); - MLN_GEN_CODE(sum, long long, x); - MLN_GEN_CODE(sum, unsigned int, x); - MLN_GEN_CODE(sum, unsigned long, x); - MLN_GEN_CODE(sum, unsigned long long, x); - MLN_GEN_CODE(sum, float, x); - MLN_GEN_CODE(sum, double, x); - MLN_GEN_CODE(sum, long double, x); - MLN_FUNCTIONAL_GEN_UNARY_CODE(sum); - - MLN_GEN_CODE(prod, int, x); - MLN_GEN_CODE(prod, long, x); - MLN_GEN_CODE(prod, long long, x); - MLN_GEN_CODE(prod, unsigned int, x); - MLN_GEN_CODE(prod, unsigned long, x); - MLN_GEN_CODE(prod, unsigned long long, x); - MLN_GEN_CODE(prod, float, x); - MLN_GEN_CODE(prod, double, x); - MLN_GEN_CODE(prod, long double, x); - MLN_FUNCTIONAL_GEN_UNARY_CODE(prod); - -#undef MLN_GEN_CODE -#undef MLN_GEN_BINARY_CODE -#undef MLN_GEN_CODE_2 -#undef MLN_FUNCTIONAL_GEN_UNARY_CODE -#undef MLN_FUNCTIONAL_GEN_BINARY_CODE -#undef MLN_FUNCTIONAL_GEN_CODE_2 -} // namespace mln diff --git a/pylene/include/mln/core/private/def_functional_ops_gen_code_macros.hpp b/pylene/include/mln/core/private/def_functional_ops_gen_code_macros.hpp new file mode 100644 index 00000000..0c283c62 --- /dev/null +++ b/pylene/include/mln/core/private/def_functional_ops_gen_code_macros.hpp @@ -0,0 +1,43 @@ + +#define MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE(FUN) \ + namespace functional \ + { \ + using mln::FUN; \ + template \ + struct FUN##_t \ + { \ + typedef decltype(FUN(std::declval())) result_type; \ + \ + auto operator()(const T& x) const -> decltype(FUN(x)) { return FUN(x); } \ + }; \ + template <> \ + struct FUN##_t \ + { \ + template \ + auto operator()(const T& x) const -> decltype(FUN(x)) \ + { \ + return FUN(x); \ + } \ + }; \ + } + +#define MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE(FUN) \ + namespace functional \ + { \ + using mln::FUN; \ + template \ + struct FUN##_t \ + { \ + typedef decltype(FUN(std::declval(), std::declval())) result_type; \ + auto operator()(const T1& x, const T2& y) const -> decltype(FUN(x, y)) { return FUN(x, y); } \ + }; \ + template <> \ + struct FUN##_t \ + { \ + template \ + auto operator()(const T1& x, const T2& y) const -> decltype(FUN(x, y)) \ + { \ + return FUN(x, y); \ + } \ + }; \ + } diff --git a/pylene/include/mln/core/private/def_maths_ops_gen_code_macros.hpp b/pylene/include/mln/core/private/def_maths_ops_gen_code_macros.hpp new file mode 100644 index 00000000..338911a1 --- /dev/null +++ b/pylene/include/mln/core/private/def_maths_ops_gen_code_macros.hpp @@ -0,0 +1,12 @@ + +#define MLN_PRIVATE_GEN_UNARY_CODE(FUN, TYPE, OP) \ + inline TYPE FUN(TYPE x) { return OP; } + +#define MLN_PRIVATE_GEN_BINARY_CODE(FUN, TYPE, OP) \ + inline TYPE FUN(TYPE x, TYPE y) { return OP; } + +#define MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(TEMPLATE, FUN, TYPE, OP) \ + TEMPLATE inline TYPE FUN(TYPE x) { return OP; } + +#define MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(TEMPLATE, FUN, TYPE, OP) \ + TEMPLATE inline TYPE FUN(TYPE x, TYPE y) { return OP; } diff --git a/pylene/include/mln/core/private/maths_ops.hpp b/pylene/include/mln/core/private/maths_ops.hpp new file mode 100644 index 00000000..263e7365 --- /dev/null +++ b/pylene/include/mln/core/private/maths_ops.hpp @@ -0,0 +1,388 @@ +#pragma once + +/** + * \file + * \brief Define fundamental mathematical and statistical operators + * + */ + +#include +#include +#include + + +#include + +namespace mln +{ + using std::cbrt; + using std::pow; + using std::sqrt; + + /* Element wise operators */ + int sqr(int x); + long sqr(long n); + long long sqr(long long n); + unsigned int sqr(unsigned int x); + unsigned long sqr(unsigned long n); + unsigned long long sqr(unsigned long long n); + float sqr(float x); + double sqr(double x); + long double sqr(long double x); + + int abs(int x); + long abs(long n); + long long abs(long long n); + unsigned int abs(unsigned int x); + unsigned long abs(unsigned long n); + unsigned long long abs(unsigned long long n); + float abs(float x); + double abs(double x); + long double abs(long double x); + + /* Reduction operators */ + int sum(int x); + long sum(long n); + long long sum(long long n); + unsigned int sum(unsigned int x); + unsigned long sum(unsigned long n); + unsigned long long sum(unsigned long long n); + float sum(float x); + double sum(double x); + long double sum(long double x); + + int prod(int x); + long prod(long n); + long long prod(long long n); + unsigned int prod(unsigned int x); + unsigned long prod(unsigned long n); + unsigned long long prod(unsigned long long n); + float prod(float x); + double prod(double x); + long double prod(long double x); + + int minimum(int x); + long minimum(long n); + long long minimum(long long n); + unsigned int minimum(unsigned int x); + unsigned long minimum(unsigned long n); + unsigned long long minimum(unsigned long long n); + float minimum(float x); + double minimum(double x); + long double minimum(long double x); + + int maximum(int x); + long maximum(long n); + long long maximum(long long n); + unsigned int maximum(unsigned int x); + unsigned long maximum(unsigned long n); + unsigned long long maximum(unsigned long long n); + float maximum(float x); + double maximum(double x); + long double maximum(long double x); + + int l0norm(int x); + long l0norm(long n); + long long l0norm(long long n); + unsigned int l0norm(unsigned int x); + unsigned long l0norm(unsigned long n); + unsigned long long l0norm(unsigned long long n); + float l0norm(float x); + double l0norm(double x); + long double l0norm(long double x); + + int l1norm(int x); + long l1norm(long n); + long long l1norm(long long n); + unsigned int l1norm(unsigned int x); + unsigned long l1norm(unsigned long n); + unsigned long long l1norm(unsigned long long n); + float l1norm(float x); + double l1norm(double x); + long double l1norm(long double x); + + int l2norm(int x); + long l2norm(long n); + long long l2norm(long long n); + unsigned int l2norm(unsigned int x); + unsigned long l2norm(unsigned long n); + unsigned long long l2norm(unsigned long long n); + float l2norm(float x); + double l2norm(double x); + long double l2norm(long double x); + + int l2dist(int x, int y); + long l2dist(long x, long y); + long long l2dist(long long x, long long y); + unsigned int l2dist(unsigned int x, unsigned int y); + unsigned long l2dist(unsigned long x, unsigned long y); + unsigned long long l2dist(unsigned long long x, unsigned long long y); + float l2dist(float x, float y); + double l2dist(double x, double y); + long double l2dist(long double x, long double y); + + int l1dist(int x, int y); + long l1dist(long x, long y); + long long l1dist(long long x, long long y); + unsigned int l1dist(unsigned int x, unsigned int y); + unsigned long l1dist(unsigned long x, unsigned long y); + unsigned long long l1dist(unsigned long long x, unsigned long long y); + float l1dist(float x, float y); + double l1dist(double x, double y); + long double l1dist(long double x, long double y); + + int l2norm_sqr(int x); + long l2norm_sqr(long n); + long long l2norm_sqr(long long n); + unsigned int l2norm_sqr(unsigned int x); + unsigned long l2norm_sqr(unsigned long n); + unsigned long long l2norm_sqr(unsigned long long n); + float l2norm_sqr(float x); + double l2norm_sqr(double x); + long double l2norm_sqr(long double x); + + int l2dist_sqr(int x, int y); + long l2dist_sqr(long x, long y); + long long l2dist_sqr(long long x, long long y); + unsigned int l2dist_sqr(unsigned int x, unsigned int y); + unsigned long l2dist_sqr(unsigned long x, unsigned long y); + unsigned long long l2dist_sqr(unsigned long long x, unsigned long long y); + float l2dist_sqr(float x, float y); + double l2dist_sqr(double x, double y); + long double l2dist_sqr(long double x, long double y); + + int linfnorm(int x); + long linfnorm(long n); + long long linfnorm(long long n); + unsigned int linfnorm(unsigned int x); + unsigned long linfnorm(unsigned long n); + unsigned long long linfnorm(unsigned long long n); + float linfnorm(float x); + double linfnorm(double x); + long double linfnorm(long double x); + + template + int lpnorm(int x); + template + long lpnorm(long x); + template + long long lpnorm(long long x); + template + unsigned int lpnorm(unsigned int x); + template + unsigned long lpnorm(unsigned long n); + template + unsigned long long lpnorm(unsigned long long n); + template + float lpnorm(float x); + template + double lpnorm(double x); + template + long double lpnorm(long double x); + + template + int lpdist(int x, int y); + template + long lpdist(long x, long y); + template + long long lpdist(long long x, long long y); + template + unsigned int lpdist(unsigned int x, unsigned int y); + template + unsigned long lpdist(unsigned long x, unsigned long y); + template + unsigned long long lpdist(unsigned long long x, unsigned long long y); + template + float lpdist(float x, float y); + template + double lpdist(double x, double y); + template + long double lpdist(long double x, long double y); + + + /********************************/ + /*** Implementation **/ + /********************************/ + MLN_PRIVATE_GEN_UNARY_CODE(sqr, int, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, long, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, long long, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, unsigned int, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, unsigned long, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, unsigned long long, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, float, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, double, x* x); + MLN_PRIVATE_GEN_UNARY_CODE(sqr, long double, x* x); + + MLN_PRIVATE_GEN_UNARY_CODE(abs, int, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(abs, long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(abs, long long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(abs, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(abs, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(abs, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(abs, float, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(abs, double, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(abs, long double, std::abs(x)); + + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, int, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, long long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, float, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, double, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l0norm, long double, std::abs(x)); + + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, int, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, long long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, float, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, double, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l1norm, long double, std::abs(x)); + + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, int, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, long long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, float, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, double, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm, long double, std::abs(x)); + + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, int, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, long, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, long long, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, unsigned int, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, unsigned long, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, unsigned long long, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, float, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, double, abs(x - y)); + MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE(template , lpdist, long double, abs(x - y)); + + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, int, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, long long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, unsigned int, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, unsigned long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, unsigned long long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, float, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, double, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist, long double, abs(x - y)); + + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, int, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, long long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, unsigned int, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, unsigned long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, unsigned long long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, float, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, double, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l1dist, long double, abs(x - y)); + + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, int, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, long long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, unsigned int, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, unsigned long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, unsigned long long, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, float, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, double, abs(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l0dist, long double, abs(x - y)); + + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, int, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, long, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, long long, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, unsigned int, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, unsigned long, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, unsigned long long, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, float, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, double, sqr(x)); + MLN_PRIVATE_GEN_UNARY_CODE(l2norm_sqr, long double, sqr(x)); + + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, int, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, long long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, unsigned int, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, unsigned long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, unsigned long long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, float, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, double, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, long double, sqr(x - y)); + + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, int, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, long long, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, float, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, double, std::abs(x)); + MLN_PRIVATE_GEN_UNARY_CODE(linfnorm, long double, std::abs(x)); + + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, int, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, long long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, unsigned int, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, unsigned long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, unsigned long long, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, float, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, double, sqr(x - y)); + MLN_PRIVATE_GEN_BINARY_CODE(linfdist, long double, sqr(x - y)); + + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, int, std::abs(x)); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, long, std::abs(x)); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, long long, std::abs(x)); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, unsigned int, x); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, unsigned long, x); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, unsigned long long, x); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, float, std::abs(x)); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, double, std::abs(x)); + MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE(template , lpnorm, long double, std::abs(x)); + + MLN_PRIVATE_GEN_UNARY_CODE(maximum, int, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, long, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, float, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, double, x); + MLN_PRIVATE_GEN_UNARY_CODE(maximum, long double, x); + + MLN_PRIVATE_GEN_UNARY_CODE(minimum, int, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, long, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, float, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, double, x); + MLN_PRIVATE_GEN_UNARY_CODE(minimum, long double, x); + + MLN_PRIVATE_GEN_UNARY_CODE(sum, int, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, long, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, float, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, double, x); + MLN_PRIVATE_GEN_UNARY_CODE(sum, long double, x); + + MLN_PRIVATE_GEN_UNARY_CODE(prod, int, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, long, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, unsigned int, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, unsigned long, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, unsigned long long, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, float, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, double, x); + MLN_PRIVATE_GEN_UNARY_CODE(prod, long double, x); + +} // namespace mln + +#include diff --git a/pylene/include/mln/core/private/undef_functional_ops_gen_code_macros.hpp b/pylene/include/mln/core/private/undef_functional_ops_gen_code_macros.hpp new file mode 100644 index 00000000..ff5b8387 --- /dev/null +++ b/pylene/include/mln/core/private/undef_functional_ops_gen_code_macros.hpp @@ -0,0 +1,3 @@ + +#undef MLN_PRIVATE_FUNCTIONAL_GEN_UNARY_CODE +#undef MLN_PRIVATE_FUNCTIONAL_GEN_BINARY_CODE diff --git a/pylene/include/mln/core/private/undef_maths_ops_gen_code_macros.hpp b/pylene/include/mln/core/private/undef_maths_ops_gen_code_macros.hpp new file mode 100644 index 00000000..76927dc5 --- /dev/null +++ b/pylene/include/mln/core/private/undef_maths_ops_gen_code_macros.hpp @@ -0,0 +1,5 @@ + +#undef MLN_PRIVATE_GEN_UNARY_CODE +#undef MLN_PRIVATE_GEN_BINARY_CODE +#undef MLN_PRIVATE_GEN_TEMPLATED_UNARY_CODE +#undef MLN_PRIVATE_GEN_TEMPLATED_BINARY_CODE diff --git a/pylene/include/mln/core/vec.hpp b/pylene/include/mln/core/vec.hpp index 2477814e..a7e779e8 100644 --- a/pylene/include/mln/core/vec.hpp +++ b/pylene/include/mln/core/vec.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include diff --git a/pylene/include/mln/core/vec/private/def_gen_code_macros.hpp b/pylene/include/mln/core/vec/private/def_gen_code_macros.hpp new file mode 100644 index 00000000..6bc95ed4 --- /dev/null +++ b/pylene/include/mln/core/vec/private/def_gen_code_macros.hpp @@ -0,0 +1,26 @@ + +#define MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, fun) internal::vec_base())), dim, tag> + +#define MLN_VEC_PRIVATE_PROMOTE(T1, T2) decltype(std::declval() + std::declval()) + +#define MLN_VEC_PRIVATE_PROMOTE_FUN(T, fun) decltype(fun(std::declval())) + +#define MLN_VEC_PRIVATE_PROMOTE_FUNCOMP(T, f, g) decltype(f(g(std::declval()))) + +#define MLN_VEC_PRIVATE_GEN_UNARY_CODE(FUN) \ + template \ + inline MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, FUN) FUN(const internal::vec_base& x) \ + { \ + MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, FUN) res; \ + for (unsigned i = 0; i < dim; ++i) \ + res[i] = FUN(x[i]); \ + return res; \ + } + +#define MLN_VEC_PRIVATE_GEN_BINARY_CODE(FUN, FUNBASE, EXPR) \ + template \ + inline auto FUN(const internal::vec_base& x, const internal::vec_base& y) \ + ->decltype(FUNBASE(EXPR)) \ + { \ + return FUNBASE(EXPR); \ + } diff --git a/pylene/include/mln/core/vec/private/undef_gen_code_macros.hpp b/pylene/include/mln/core/vec/private/undef_gen_code_macros.hpp new file mode 100644 index 00000000..ddf412c3 --- /dev/null +++ b/pylene/include/mln/core/vec/private/undef_gen_code_macros.hpp @@ -0,0 +1,7 @@ + +#undef MLN_VEC_PRIVATE_PROMOTE_FUN +#undef MLN_VEC_PRIVATE_PROMOTE +#undef MLN_VEC_PRIVATE_PROMOTE_FUN +#undef MLN_VEC_PRIVATE_PROMOTE_FUNCOMP +#undef MLN_VEC_PRIVATE_GEN_UNARY_CODE +#undef MLN_VEC_PRIVATE_GEN_BINARY_CODE diff --git a/pylene/include/mln/core/vec/vec_math_ops.hpp b/pylene/include/mln/core/vec/vec_math_ops.hpp deleted file mode 100644 index f0dfb5ec..00000000 --- a/pylene/include/mln/core/vec/vec_math_ops.hpp +++ /dev/null @@ -1,276 +0,0 @@ -#pragma once - -#include -#include - - -/** - * \file Define vectorial overloads for fundamental mathematical and - * statistical operators - * - */ - -#define MLN_VEC_PROMOTE_FUN(T, dim, tag, fun) internal::vec_base())), dim, tag> - -#define MLN_PROMOTE(T1, T2) decltype(std::declval() + std::declval()) - -#define MLN_PROMOTE_FUN(T, fun) decltype(fun(std::declval())) - -#define MLN_PROMOTE_FUNCOMP(T, f, g) decltype(f(g(std::declval()))) - -namespace mln -{ - - /* Element wise operators */ - template - internal::vec_base(), std::declval())), dim, tag> - pow(const internal::vec_base& x, V exp); - - template - MLN_VEC_PROMOTE_FUN(T, dim, tag, sqr) - sqr(const internal::vec_base& x); - - template - MLN_VEC_PROMOTE_FUN(T, dim, tag, abs) - abs(const internal::vec_base& x); - - template - MLN_VEC_PROMOTE_FUN(T, dim, tag, sqrt) - sqrt(const internal::vec_base& x); - - template - MLN_VEC_PROMOTE_FUN(T, dim, tag, cqrt) - cbrt(const internal::vec_base& x); - - /* algebraic operators */ - template - MLN_PROMOTE(U, V) - dot(const internal::vec_base& x, const internal::vec_base& y); - - template - internal::vec_base cross(const internal::vec_base& x, - const internal::vec_base& y); - - /* Reduction operators */ - - template - MLN_PROMOTE(T, T) - sum(const internal::vec_base& x); - - template - MLN_PROMOTE(T, T) - prod(const internal::vec_base& x); - - template - T maximum(const internal::vec_base& x); - - template - T minimum(const internal::vec_base& x); - - template - MLN_PROMOTE_FUN(T, abs) - l0norm(const internal::vec_base& x); - - template - MLN_PROMOTE_FUN(T, abs) - linfnorm(const internal::vec_base& x); - - template - MLN_PROMOTE_FUN(T, abs) - l1norm(const internal::vec_base& x); - - template - MLN_PROMOTE_FUNCOMP(T, sqrt, sqr) - l2norm(const internal::vec_base& x); - - template - inline MLN_PROMOTE_FUN(T, sqr) l2norm_sqr(const internal::vec_base& x); - - template - MLN_PROMOTE_FUNCOMP(T, pow, abs) - lpnorm(const internal::vec_base& x); - - template - inline auto l1dist(const internal::vec_base& x, const internal::vec_base& y) - -> decltype(l1norm(x - y)); - - template - inline auto l2dist(const internal::vec_base& x, const internal::vec_base& y) - -> decltype(l2norm(x - y)); - - template - inline auto l2dist_sqr(const internal::vec_base& x, const internal::vec_base& y) - -> decltype(l2norm_sqr(x - y)); - - /*****************************/ - /** Implementation ***/ - /*****************************/ - -#define MLN_GEN_CODE(FUN) \ - template \ - inline MLN_VEC_PROMOTE_FUN(T, dim, tag, FUN) FUN(const internal::vec_base& x) \ - { \ - MLN_VEC_PROMOTE_FUN(T, dim, tag, FUN) res; \ - for (unsigned i = 0; i < dim; ++i) \ - res[i] = FUN(x[i]); \ - return res; \ - } - -#define MLN_GEN_BINARY_CODE(FUN, FUNBASE, EXPR) \ - template \ - inline auto FUN(const internal::vec_base& x, const internal::vec_base& y) \ - ->decltype(FUNBASE(EXPR)) \ - { \ - return FUNBASE(EXPR); \ - } - - MLN_GEN_CODE(sqr); - MLN_GEN_CODE(sqrt); - MLN_GEN_CODE(abs); - MLN_GEN_CODE(cbrt); - - MLN_GEN_BINARY_CODE(l1dist, l1norm, x - y); - MLN_GEN_BINARY_CODE(l2dist, l2norm, x - y); - MLN_GEN_BINARY_CODE(l2dist_sqr, l2norm_sqr, x - y); - - template - internal::vec_base(), std::declval())), dim, tag> - pow(const internal::vec_base& x, V exp) - { - typedef decltype(pow(std::declval(), std::declval())) R; - internal::vec_base res; - for (unsigned i = 0; i < dim; ++i) - res[i] = pow(x[i], exp); - return res; - } - - template - MLN_PROMOTE(U, V) - dot(const internal::vec_base& x, const internal::vec_base& y) - { - MLN_PROMOTE(U, V) res = 0; - for (int i = 0; i < dim; ++i) - res += x[i] * y[i]; - return res; - } - - template - internal::vec_base cross(const internal::vec_base& u, - const internal::vec_base& v) - { - return {u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]}; - } - - template - inline MLN_PROMOTE(T, T) sum(const internal::vec_base& x) - { - MLN_PROMOTE(T, T) res = x[0]; - for (unsigned i = 1; i < dim; ++i) - res += x[i]; - return res; - } - - template - inline MLN_PROMOTE(T, T) prod(const internal::vec_base& x) - { - MLN_PROMOTE(T, T) res = x[0]; - for (unsigned i = 1; i < dim; ++i) - res *= x[i]; - return res; - } - - template - inline T maximum(const internal::vec_base& x) - { - T res = x[0]; - for (unsigned i = 1; i < dim; ++i) - if (res < x[i]) - res = x[i]; - return res; - } - - template - inline T minimum(const internal::vec_base& x) - { - T res = x[0]; - for (unsigned i = 1; i < dim; ++i) - if (x[i] < res) - res = x[i]; - return res; - } - - template - inline MLN_PROMOTE_FUN(T, abs) l0norm(const internal::vec_base& x) - { - typedef MLN_PROMOTE_FUN(T, abs) U; - U res = abs(x[0]); - for (unsigned i = 1; i < dim; ++i) - { - U v = abs(x[i]); - if (v < res) - res = v; - } - return res; - } - - template - inline MLN_PROMOTE_FUN(T, abs) linfnorm(const internal::vec_base& x) - { - typedef MLN_PROMOTE_FUN(T, abs) U; - U res = abs(x[0]); - for (unsigned i = 1; i < dim; ++i) - { - U v = abs(x[i]); - if (res < v) - res = v; - } - return res; - } - - template - inline MLN_PROMOTE_FUN(T, abs) l1norm(const internal::vec_base& x) - { - typedef MLN_PROMOTE_FUN(T, abs) U; - U res = abs(x[0]); - for (unsigned i = 1; i < dim; ++i) - res += abs(x[i]); - return res; - } - - template - inline MLN_PROMOTE_FUNCOMP(T, sqrt, sqr) l2norm(const internal::vec_base& x) - { - typedef MLN_PROMOTE_FUNCOMP(T, sqrt, sqr) U; - U res = sqr(x[0]); - for (unsigned i = 1; i < dim; ++i) - res += sqr(x[i]); - return sqrt(res); - } - - template - inline MLN_PROMOTE_FUN(T, sqr) l2norm_sqr(const internal::vec_base& x) - { - typedef MLN_PROMOTE_FUNCOMP(T, sqrt, sqr) U; - U res = sqr(x[0]); - for (unsigned i = 1; i < dim; ++i) - res += sqr(x[i]); - return res; - } - - template - MLN_PROMOTE_FUNCOMP(T, pow, abs) - lpnorm(const internal::vec_base& x) - { - typedef MLN_PROMOTE_FUNCOMP(T, pow, abs) U; - U res = pow(abs(x[0]), p); - for (unsigned i = 1; i < dim; ++i) - res += pow(abs(x[i]), p); - return pow(res, 1 / p); - } -} // namespace mln - -#undef MLN_GEN_CODE -#undef MLN_GEN_BINARY_CODE -#undef MLN_VEC_PROMOTE_FUN -#undef MLN_VEC_PROMOTE -#undef MLN_PROMOTE_FUNCOMP diff --git a/pylene/include/mln/core/vec/vec_maths_ops.hpp b/pylene/include/mln/core/vec/vec_maths_ops.hpp new file mode 100644 index 00000000..69ab3b35 --- /dev/null +++ b/pylene/include/mln/core/vec/vec_maths_ops.hpp @@ -0,0 +1,296 @@ +#pragma once + +#include +#include + +/** + * \file Define vectorial overloads for fundamental mathematical and + * statistical operators + * + */ + +#include + +namespace mln +{ + /* Element wise operators */ + template + internal::vec_base(), std::declval())), dim, tag> + pow(const internal::vec_base& x, V exp); + + template + MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, sqr) + sqr(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, abs) + abs(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, sqrt) + sqrt(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_VEC_PROMOTE_FUN(T, dim, tag, cqrt) + cbrt(const internal::vec_base& x); + + /* algebraic operators */ + template + MLN_VEC_PRIVATE_PROMOTE(U, V) + dot(const internal::vec_base& x, const internal::vec_base& y); + + template + internal::vec_base cross(const internal::vec_base& x, + const internal::vec_base& y); + template + internal::vec_base cross(const internal::vec_base& x, + const internal::vec_base& y); + template + internal::vec_base cross(const internal::vec_base& x, + const internal::vec_base& y); + + /* Reduction operators */ + + template + MLN_VEC_PRIVATE_PROMOTE(T, T) + sum(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_PROMOTE(T, T) + prod(const internal::vec_base& x); + + template + T maximum(const internal::vec_base& x); + + template + T minimum(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) + l0norm(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) + linfnorm(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) + l1norm(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_PROMOTE_FUNCOMP(T, sqrt, sqr) + l2norm(const internal::vec_base& x); + + template + inline MLN_VEC_PRIVATE_PROMOTE_FUN(T, sqr) l2norm_sqr(const internal::vec_base& x); + + template + MLN_VEC_PRIVATE_PROMOTE_FUNCOMP(T, pow, abs) + lpnorm(const internal::vec_base& x); + + template + inline auto l0dist(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(l0norm(x - y)); + + template + inline auto l1dist(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(l1norm(x - y)); + + template + inline auto l2dist(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(l2norm(x - y)); + + template + inline auto lpdist(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(lpnorm

(x - y)); + + template + inline auto l2dist_sqr(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(l2norm_sqr(x - y)); + + template + inline auto linfdist(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(linfnorm(x - y)); + + /*****************************/ + /** Implementation ***/ + /*****************************/ + + MLN_VEC_PRIVATE_GEN_UNARY_CODE(sqr); + MLN_VEC_PRIVATE_GEN_UNARY_CODE(sqrt); + MLN_VEC_PRIVATE_GEN_UNARY_CODE(abs); + MLN_VEC_PRIVATE_GEN_UNARY_CODE(cbrt); + + MLN_VEC_PRIVATE_GEN_BINARY_CODE(l0dist, l0norm, x - y); + MLN_VEC_PRIVATE_GEN_BINARY_CODE(l1dist, l1norm, x - y); + MLN_VEC_PRIVATE_GEN_BINARY_CODE(l2dist, l2norm, x - y); + MLN_VEC_PRIVATE_GEN_BINARY_CODE(l2dist_sqr, l2norm_sqr, x - y); + MLN_VEC_PRIVATE_GEN_BINARY_CODE(linfdist, linfnorm, x - y); + + template + inline auto lpdist(const internal::vec_base& x, const internal::vec_base& y) + -> decltype(lpnorm

(x - y)) + { + return lpnorm

(x - y); + } + + + template + internal::vec_base(), std::declval())), dim, tag> + pow(const internal::vec_base& x, V exp) + { + typedef decltype(pow(std::declval(), std::declval())) R; + + internal::vec_base res; + for (unsigned i = 0; i < dim; ++i) + res[i] = pow(x[i], exp); + return res; + } + + template + MLN_VEC_PRIVATE_PROMOTE(U, V) + dot(const internal::vec_base& x, const internal::vec_base& y) + { + MLN_VEC_PRIVATE_PROMOTE(U, V) res = 0; + for (unsigned i = 0; i < dim; ++i) + res += x[i] * y[i]; + return res; + } + + template + internal::vec_base cross(const internal::vec_base& u, + const internal::vec_base& v) + { + return {u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]}; + } + + template + internal::vec_base cross(const internal::vec_base& u, + const internal::vec_base& v) + { + // cf. https://en.wikipedia.org/wiki/Seven-dimensional_cross_product#Coordinate_expressions + return {u[1] * v[3] - u[3] * v[1] + u[2] * v[6] - u[6] * v[2] + u[4] * v[5] - u[5] * v[4], + u[2] * v[4] - u[4] * v[2] + u[3] * v[0] - u[0] * v[3] + u[5] * v[6] - u[6] * v[5], + u[3] * v[5] - u[5] * v[3] + u[4] * v[1] - u[1] * v[4] + u[6] * v[0] - u[0] * v[6], + u[4] * v[6] - u[6] * v[4] + u[5] * v[2] - u[2] * v[5] + u[0] * v[1] - u[1] * v[0], + u[5] * v[0] - u[0] * v[5] + u[6] * v[3] - u[3] * v[6] + u[1] * v[2] - u[2] * v[1], + u[6] * v[1] - u[1] * v[6] + u[0] * v[4] - u[4] * v[0] + u[2] * v[3] - u[3] * v[2], + u[0] * v[2] - u[2] * v[0] + u[1] * v[5] - u[5] * v[1] + u[3] * v[4] - u[4] * v[3]}; + } + + template + internal::vec_base + cross([[maybe_unused]] const internal::vec_base& u, + [[maybe_unused]] const internal::vec_base& v) + { + static_assert(dim != 3 && dim != 7, "cross product is only defined for vector of size 3 or 7"); + } + + template + inline MLN_VEC_PRIVATE_PROMOTE(T, T) sum(const internal::vec_base& x) + { + MLN_VEC_PRIVATE_PROMOTE(T, T) res = x[0]; + for (unsigned i = 1; i < dim; ++i) + res += x[i]; + return res; + } + + template + inline MLN_VEC_PRIVATE_PROMOTE(T, T) prod(const internal::vec_base& x) + { + MLN_VEC_PRIVATE_PROMOTE(T, T) res = x[0]; + for (unsigned i = 1; i < dim; ++i) + res *= x[i]; + return res; + } + + template + inline T maximum(const internal::vec_base& x) + { + T res = x[0]; + for (unsigned i = 1; i < dim; ++i) + if (res < x[i]) + res = x[i]; + return res; + } + + template + inline T minimum(const internal::vec_base& x) + { + T res = x[0]; + for (unsigned i = 1; i < dim; ++i) + if (x[i] < res) + res = x[i]; + return res; + } + + template + inline MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) l0norm(const internal::vec_base& x) + { + typedef MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) U; + U res = abs(x[0]); + for (unsigned i = 1; i < dim; ++i) + { + U v = abs(x[i]); + if (v < res) + res = v; + } + return res; + } + + template + inline MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) linfnorm(const internal::vec_base& x) + { + typedef MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) U; + U res = abs(x[0]); + for (unsigned i = 1; i < dim; ++i) + { + U v = abs(x[i]); + if (res < v) + res = v; + } + return res; + } + + template + inline MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) l1norm(const internal::vec_base& x) + { + typedef MLN_VEC_PRIVATE_PROMOTE_FUN(T, abs) U; + U res = abs(x[0]); + for (unsigned i = 1; i < dim; ++i) + res += abs(x[i]); + return res; + } + + template + inline MLN_VEC_PRIVATE_PROMOTE_FUNCOMP(T, sqrt, sqr) l2norm(const internal::vec_base& x) + { + typedef MLN_VEC_PRIVATE_PROMOTE_FUNCOMP(T, sqrt, sqr) U; + U res = sqr(x[0]); + for (unsigned i = 1; i < dim; ++i) + res += sqr(x[i]); + return sqrt(res); + } + + template + inline MLN_VEC_PRIVATE_PROMOTE_FUN(T, sqr) l2norm_sqr(const internal::vec_base& x) + { + typedef MLN_VEC_PRIVATE_PROMOTE_FUNCOMP(T, sqrt, sqr) U; + U res = sqr(x[0]); + for (unsigned i = 1; i < dim; ++i) + res += sqr(x[i]); + return res; + } + + template + decltype(pow(abs(std::declval()), p)) lpnorm(const internal::vec_base& x) + { + using U = decltype(pow(abs(std::declval()), p)); + U res = pow(abs(x[0]), p); + for (unsigned i = 1; i < dim; ++i) + res += pow(abs(x[i]), p); + return pow(res, 1 / p); + } +} // namespace mln + +#include diff --git a/pylene/include/mln/morpho/structural/gradient.hpp b/pylene/include/mln/morpho/structural/gradient.hpp index 9b9313d3..1de42be5 100644 --- a/pylene/include/mln/morpho/structural/gradient.hpp +++ b/pylene/include/mln/morpho/structural/gradient.hpp @@ -1,8 +1,8 @@ #pragma once #include +#include #include -#include #include #include #include diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp index 6f264056..a96d02ee 100644 --- a/tests/core/image/view/maths.cpp +++ b/tests/core/image/view/maths.cpp @@ -6,8 +6,6 @@ #include #include -#include - #include @@ -17,7 +15,6 @@ TEST(View, maths_abs) using namespace view::ops; using namespace view::maths; - image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // {10, -11, 12, -13, 14}}; @@ -27,6 +24,17 @@ TEST(View, maths_abs) {10, 11, 12, 13, 14}}; ASSERT_TRUE(all_of(ref == abs(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + ASSERT_TRUE(all_of(ref2 == abs(ima2))); } TEST(View, maths_sqr) @@ -44,6 +52,17 @@ TEST(View, maths_sqr) {100, 121, 144, 169, 196}}; ASSERT_TRUE(all_of(ref == sqr(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}}; + + ASSERT_TRUE(all_of(ref2 == sqr(ima2))); } TEST(View, maths_pow) @@ -59,6 +78,17 @@ TEST(View, maths_pow) auto ima = view::transform(ref, [](auto x) { return x * x * x; }); ASSERT_TRUE(all_of(pow(ref, 3) == ima)); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}, // + {{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}, // + {{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}}; + + ASSERT_TRUE(all_of(ref2 == pow(ima2, 3))); } TEST(View, maths_sqrt) @@ -76,6 +106,17 @@ TEST(View, maths_sqrt) {10, 11, 12, 13, 14}}; ASSERT_TRUE(all_of(ref == sqrt(ima))); + + + image2d ima2 = {{{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}}; + + image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + ASSERT_TRUE(all_of(ref2 == sqrt(ima2))); } TEST(View, maths_cbrt) @@ -91,6 +132,15 @@ TEST(View, maths_cbrt) auto ima = pow(ref, 3); ASSERT_TRUE(all_of(ref == view::cast(cbrt(ima)))); + + + image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + auto ima2 = pow(ref2, 3); + + ASSERT_TRUE(all_of(ref2 == view::cast(cbrt(ima2)))); } TEST(View, maths_sum) @@ -99,7 +149,6 @@ TEST(View, maths_sum) using namespace view::ops; using namespace view::maths; - image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // {10, -11, 12, -13, 14}}; @@ -128,7 +177,6 @@ TEST(View, maths_prod) using namespace view::ops; using namespace view::maths; - image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // {10, -11, 12, -13, 14}}; @@ -151,12 +199,109 @@ TEST(View, maths_prod) ASSERT_TRUE(all_of(ref2 == prod(ima2))); } -TEST(View, maths_l0norm) +TEST(View, maths_cross) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima2 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref = {{{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}, // + {{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}, // + {{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}}; + + ASSERT_TRUE(all_of(ref == cross(ima1, ima2))); +} + +TEST(View, maths_dot) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima2 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref = {{50, 77, 50}, // + {50, 77, 50}, // + {50, 77, 50}}; + + ASSERT_TRUE(all_of(ref == dot(ima1, ima2))); +} + +TEST(View, maths_min) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == min(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{1, 4, 7}, // + {1, 4, 7}, // + {1, 4, 7}}; + + ASSERT_TRUE(all_of(ref2 == min(ima2))); +} + +TEST(View, maths_max) { using namespace mln; using namespace view::ops; using namespace view::maths; + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == max(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{3, 6, 9}, // + {3, 6, 9}, // + {3, 6, 9}}; + + ASSERT_TRUE(all_of(ref2 == max(ima2))); +} + +TEST(View, maths_l0norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // @@ -186,7 +331,6 @@ TEST(View, maths_l1norm) using namespace view::ops; using namespace view::maths; - image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // {10, -11, 12, -13, 14}}; @@ -215,7 +359,6 @@ TEST(View, maths_l2norm) using namespace view::ops; using namespace view::maths; - image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // {10, -11, 12, -13, 14}}; @@ -238,12 +381,67 @@ TEST(View, maths_l2norm) ASSERT_TRUE(all_of(ref2 == l2norm(ima2))); } -TEST(View, maths_linfnorm) +TEST(View, maths_lpnorm) { using namespace mln; using namespace view::ops; using namespace view::maths; + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == lpnorm<4>(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{1, 1, 1}, // + {1, 1, 1}, // + {1, 1, 1}}; + + ASSERT_TRUE(all_of(ref2 == lpnorm<4>(ima2))); +} + +TEST(View, maths_l2norm_sqr) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 4, 9, 16}, // + {25, 36, 16, 64, 81}, // + {100, 121, 144, 169, 196}}; + + ASSERT_TRUE(all_of(ref == l2norm_sqr(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{14, 77, 194}, // + {14, 77, 194}, // + {14, 77, 194}}; + + ASSERT_TRUE(all_of(ref2 == l2norm_sqr(ima2))); +} + +TEST(View, maths_linfnorm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; image2d ima = {{0, -1, 2, -3, 4}, // {-5, 6, -4, 8, -9}, // @@ -264,6 +462,221 @@ TEST(View, maths_linfnorm) {3, 6, 9}, // {3, 6, 9}}; - ASSERT_IMAGES_EQ_EXP(ref2, linfnorm(ima2)); ASSERT_TRUE(all_of(ref2 == linfnorm(ima2))); } + +TEST(View, maths_l0dist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == l0dist(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}}; + + image2d ima4 = {{{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}, // + {{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}, // + {{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}}; + + image2d ref2 = {{2, 0, 2}, // + {2, 0, 2}, // + {2, 0, 2}}; + + ASSERT_TRUE(all_of(ref2 == l0dist(ima3, ima4))); +} + +TEST(View, maths_l1dist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == l1dist(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{18, 0, 18}, // + {18, 0, 18}, // + {18, 0, 18}}; + + ASSERT_TRUE(all_of(ref2 == l1dist(ima3, ima4))); +} + +TEST(View, maths_l2dist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == view::cast(l2dist(ima1, sqr(ima2))))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}, // + {{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}, // + {{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}}; + + image2d ref2 = {{6, 0, 6}, // + {6, 0, 6}, // + {6, 0, 6}}; + + ASSERT_TRUE(all_of(ref2 == view::cast(l2dist(ima3, ima4)))); +} + +TEST(View, maths_lpdist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == lpdist<4>(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{1, 1, 1}, // + {1, 1, 1}, // + {1, 1, 1}}; + + ASSERT_TRUE(all_of(ref2 == view::cast(lpdist<4>(ima3, ima4)))); +} + +TEST(View, maths_l2dist_sqr) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 4, 4, 144, 144}, // + {900, 900, 400, 3136, 8100}, // + {8100, 17424, 17424, 33124, 33124}}; + + ASSERT_TRUE(all_of(ref == l2dist_sqr(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{108, 0, 108}, // + {108, 0, 108}, // + {108, 0, 108}}; + + ASSERT_TRUE(all_of(ref2 == l2dist_sqr(ima3, ima4))); +} + +TEST(View, maths_linfdist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 4, 4, 144, 144}, // + {900, 900, 400, 3136, 8100}, // + {8100, 17424, 17424, 33124, 33124}}; + + ASSERT_TRUE(all_of(ref == linfdist(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{6, 0, 6}, // + {6, 0, 6}, // + {6, 0, 6}}; + + ASSERT_TRUE(all_of(ref2 == linfdist(ima3, ima4))); +} diff --git a/tests/core/vec/vec_math_ops.cpp b/tests/core/vec/vec_math_ops.cpp index feee37f5..d92050fa 100644 --- a/tests/core/vec/vec_math_ops.cpp +++ b/tests/core/vec/vec_math_ops.cpp @@ -1,5 +1,5 @@ +#include #include -#include #include -- GitLab From b8de0b76d573c28124a864256451e48713a37d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 9 Apr 2019 11:43:00 +0200 Subject: [PATCH 36/61] WIP doc --- doc/source/core.rst | 16 +++++++++++++--- doc/source/core/view/maths.rst | 4 ++++ doc/source/core/view/operators.rst | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 doc/source/core/view/maths.rst create mode 100644 doc/source/core/view/operators.rst diff --git a/doc/source/core.rst b/doc/source/core.rst index 319d6901..4a2fbaaa 100644 --- a/doc/source/core.rst +++ b/doc/source/core.rst @@ -92,12 +92,22 @@ See :doc:`core/images` for a description of the image concepts and image basics. | Conditional | ``view::ifelse(a, b, c)`` | +--------------+-----------------------------------------------------------+ + Cf. :doc:`core/view/operators` for examples. + .. topic:: Mathematical image operator (views) - +-------+-------+ - | FIXME | FIXME | - +-------+-------+ + +----------------+---------------------------------------------------------------------------------------------------------+ + | Component-wise | `abs(a)`, `sqr(a)`, `pow(a, p)`, `cbrt(a)`, `sqrt(a)` | + +----------------+---------------------------------------------------------------------------------------------------------+ + | Reduction | `sum(a)`, `prod(a)`, `min(a)`, `max(a)`, `dot(a, b)`, `cross(a, b)` | + +----------------+---------------------------------------------------------------------------------------------------------+ + | Norms | `l0norm(a)`, `l1norm(a)`, `l2norm(a)`, `l2norm_sqr(a)`, `linfnorm(a)`, `lpnorm

(a)` | + +----------------+---------------------------------------------------------------------------------------------------------+ + | Distances | `l0dist(a, b)`, `l1dist(a, b)`, `l2dist(a, b)`, `l2dist_sqr(a, b)`, `linfdist(a, b)`, `lpdist

(a, b)` | + +----------------+---------------------------------------------------------------------------------------------------------+ + + Cf. :doc:`core/view/maths` for examples. .. topic:: Other image operators (views) diff --git a/doc/source/core/view/maths.rst b/doc/source/core/view/maths.rst new file mode 100644 index 00000000..66235ace --- /dev/null +++ b/doc/source/core/view/maths.rst @@ -0,0 +1,4 @@ +Maths (view) +############ + + diff --git a/doc/source/core/view/operators.rst b/doc/source/core/view/operators.rst new file mode 100644 index 00000000..30404ce4 --- /dev/null +++ b/doc/source/core/view/operators.rst @@ -0,0 +1 @@ +TODO \ No newline at end of file -- GitLab From 3f7425ebdbf5936564611a7a76593a4981db7b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Tue, 9 Apr 2019 17:15:54 +0200 Subject: [PATCH 37/61] Split unit test into 4 different files for gcc to compile within a more human-bearable time (< 1h) ... --- tests/core/CMakeLists.txt | 5 +- tests/core/image/view/maths.cpp | 682 --------------------- tests/core/image/view/maths_components.cpp | 144 +++++ tests/core/image/view/maths_distances.cpp | 226 +++++++ tests/core/image/view/maths_norms.cpp | 178 ++++++ tests/core/image/view/maths_reductions.cpp | 164 +++++ 6 files changed, 716 insertions(+), 683 deletions(-) delete mode 100644 tests/core/image/view/maths.cpp create mode 100644 tests/core/image/view/maths_components.cpp create mode 100644 tests/core/image/view/maths_distances.cpp create mode 100644 tests/core/image/view/maths_norms.cpp create mode 100644 tests/core/image/view/maths_reductions.cpp diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 6ff2a1c9..953f61a9 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -22,7 +22,10 @@ add_core_test(${test_prefix}view_cast image/view/cast.cpp) add_core_test(${test_prefix}view_clip image/view/clip.cpp) add_core_test(${test_prefix}view_filter image/view/filter.cpp) add_core_test(${test_prefix}view_mask image/view/mask.cpp) -add_core_test(${test_prefix}view_maths image/view/maths.cpp) +add_core_test(${test_prefix}view_maths_comps image/view/maths_components.cpp) +add_core_test(${test_prefix}view_maths_reds image/view/maths_reductions.cpp) +add_core_test(${test_prefix}view_maths_norms image/view/maths_norms.cpp) +add_core_test(${test_prefix}view_maths_dists image/view/maths_distances.cpp) add_core_test(${test_prefix}view_ops image/view/operators.cpp) add_core_test(${test_prefix}view_transform image/view/transform.cpp) add_core_test(${test_prefix}view_zip image/view/zip.cpp) diff --git a/tests/core/image/view/maths.cpp b/tests/core/image/view/maths.cpp deleted file mode 100644 index a96d02ee..00000000 --- a/tests/core/image/view/maths.cpp +++ /dev/null @@ -1,682 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - - -TEST(View, maths_abs) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == abs(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - ASSERT_TRUE(all_of(ref2 == abs(ima2))); -} - -TEST(View, maths_sqr) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - image2d ref = {{0, 1, 4, 9, 16}, // - {25, 36, 16, 64, 81}, // - {100, 121, 144, 169, 196}}; - - ASSERT_TRUE(all_of(ref == sqr(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // - {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // - {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}}; - - ASSERT_TRUE(all_of(ref2 == sqr(ima2))); -} - -TEST(View, maths_pow) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - auto ima = view::transform(ref, [](auto x) { return x * x * x; }); - - ASSERT_TRUE(all_of(pow(ref, 3) == ima)); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}, // - {{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}, // - {{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}}; - - ASSERT_TRUE(all_of(ref2 == pow(ima2, 3))); -} - -TEST(View, maths_sqrt) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, 1, 4, 9, 16}, // - {25, 36, 16, 64, 81}, // - {100, 121, 144, 169, 196}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == sqrt(ima))); - - - image2d ima2 = {{{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // - {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // - {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}}; - - image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - ASSERT_TRUE(all_of(ref2 == sqrt(ima2))); -} - -TEST(View, maths_cbrt) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - auto ima = pow(ref, 3); - - ASSERT_TRUE(all_of(ref == view::cast(cbrt(ima)))); - - - image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - auto ima2 = pow(ref2, 3); - - ASSERT_TRUE(all_of(ref2 == view::cast(cbrt(ima2)))); -} - -TEST(View, maths_sum) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - ASSERT_TRUE(all_of(ref == sum(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{6, 15, 24}, // - {6, 15, 24}, // - {6, 15, 24}}; - - ASSERT_TRUE(all_of(ref2 == sum(ima2))); -} - -TEST(View, maths_prod) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - ASSERT_TRUE(all_of(ref == prod(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{6, 120, 504}, // - {6, 120, 504}, // - {6, 120, 504}}; - - ASSERT_TRUE(all_of(ref2 == prod(ima2))); -} - -TEST(View, maths_cross) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima2 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; - - image2d ref = {{{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}, // - {{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}, // - {{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}}; - - ASSERT_TRUE(all_of(ref == cross(ima1, ima2))); -} - -TEST(View, maths_dot) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima2 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; - - image2d ref = {{50, 77, 50}, // - {50, 77, 50}, // - {50, 77, 50}}; - - ASSERT_TRUE(all_of(ref == dot(ima1, ima2))); -} - -TEST(View, maths_min) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - ASSERT_TRUE(all_of(ref == min(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{1, 4, 7}, // - {1, 4, 7}, // - {1, 4, 7}}; - - ASSERT_TRUE(all_of(ref2 == min(ima2))); -} - -TEST(View, maths_max) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - ASSERT_TRUE(all_of(ref == max(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{3, 6, 9}, // - {3, 6, 9}, // - {3, 6, 9}}; - - ASSERT_TRUE(all_of(ref2 == max(ima2))); -} - -TEST(View, maths_l0norm) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == l0norm(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{1, 4, 7}, // - {1, 4, 7}, // - {1, 4, 7}}; - - ASSERT_TRUE(all_of(ref2 == l0norm(ima2))); -} - -TEST(View, maths_l1norm) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == l1norm(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{6, 15, 24}, // - {6, 15, 24}, // - {6, 15, 24}}; - - ASSERT_TRUE(all_of(ref2 == l1norm(ima2))); -} - -TEST(View, maths_l2norm) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == l2norm(ima))); - - - image2d ima2 = {{{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // - {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // - {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}}; - - image2d ref2 = {{3, 6, 9}, // - {3, 6, 9}, // - {3, 6, 9}}; - - ASSERT_TRUE(all_of(ref2 == l2norm(ima2))); -} - -TEST(View, maths_lpnorm) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == lpnorm<4>(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{1, 1, 1}, // - {1, 1, 1}, // - {1, 1, 1}}; - - ASSERT_TRUE(all_of(ref2 == lpnorm<4>(ima2))); -} - -TEST(View, maths_l2norm_sqr) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 4, 9, 16}, // - {25, 36, 16, 64, 81}, // - {100, 121, 144, 169, 196}}; - - ASSERT_TRUE(all_of(ref == l2norm_sqr(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{14, 77, 194}, // - {14, 77, 194}, // - {14, 77, 194}}; - - ASSERT_TRUE(all_of(ref2 == l2norm_sqr(ima2))); -} - -TEST(View, maths_linfnorm) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 1, 2, 3, 4}, // - {5, 6, 4, 8, 9}, // - {10, 11, 12, 13, 14}}; - - ASSERT_TRUE(all_of(ref == linfnorm(ima))); - - - image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ref2 = {{3, 6, 9}, // - {3, 6, 9}, // - {3, 6, 9}}; - - ASSERT_TRUE(all_of(ref2 == linfnorm(ima2))); -} - -TEST(View, maths_l0dist) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ima2 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 2, 2, 12, 12}, // - {30, 30, 20, 56, 90}, // - {90, 132, 132, 182, 182}}; - - ASSERT_TRUE(all_of(ref == l0dist(ima1, sqr(ima2)))); - - - image2d ima3 = {{{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // - {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // - {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}}; - - image2d ima4 = {{{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}, // - {{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}, // - {{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}}; - - image2d ref2 = {{2, 0, 2}, // - {2, 0, 2}, // - {2, 0, 2}}; - - ASSERT_TRUE(all_of(ref2 == l0dist(ima3, ima4))); -} - -TEST(View, maths_l1dist) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ima2 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 2, 2, 12, 12}, // - {30, 30, 20, 56, 90}, // - {90, 132, 132, 182, 182}}; - - ASSERT_TRUE(all_of(ref == l1dist(ima1, sqr(ima2)))); - - - image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; - - image2d ref2 = {{18, 0, 18}, // - {18, 0, 18}, // - {18, 0, 18}}; - - ASSERT_TRUE(all_of(ref2 == l1dist(ima3, ima4))); -} - -TEST(View, maths_l2dist) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ima2 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 2, 2, 12, 12}, // - {30, 30, 20, 56, 90}, // - {90, 132, 132, 182, 182}}; - - ASSERT_TRUE(all_of(ref == view::cast(l2dist(ima1, sqr(ima2))))); - - - image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima4 = {{{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}, // - {{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}, // - {{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}}; - - image2d ref2 = {{6, 0, 6}, // - {6, 0, 6}, // - {6, 0, 6}}; - - ASSERT_TRUE(all_of(ref2 == view::cast(l2dist(ima3, ima4)))); -} - -TEST(View, maths_lpdist) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ima2 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 2, 2, 12, 12}, // - {30, 30, 20, 56, 90}, // - {90, 132, 132, 182, 182}}; - - ASSERT_TRUE(all_of(ref == lpdist<4>(ima1, sqr(ima2)))); - - - image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; - - image2d ref2 = {{1, 1, 1}, // - {1, 1, 1}, // - {1, 1, 1}}; - - ASSERT_TRUE(all_of(ref2 == view::cast(lpdist<4>(ima3, ima4)))); -} - -TEST(View, maths_l2dist_sqr) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ima2 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 4, 4, 144, 144}, // - {900, 900, 400, 3136, 8100}, // - {8100, 17424, 17424, 33124, 33124}}; - - ASSERT_TRUE(all_of(ref == l2dist_sqr(ima1, sqr(ima2)))); - - - image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; - - image2d ref2 = {{108, 0, 108}, // - {108, 0, 108}, // - {108, 0, 108}}; - - ASSERT_TRUE(all_of(ref2 == l2dist_sqr(ima3, ima4))); -} - -TEST(View, maths_linfdist) -{ - using namespace mln; - using namespace view::ops; - using namespace view::maths; - - image2d ima1 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ima2 = {{0, -1, 2, -3, 4}, // - {-5, 6, -4, 8, -9}, // - {10, -11, 12, -13, 14}}; - - image2d ref = {{0, 4, 4, 144, 144}, // - {900, 900, 400, 3136, 8100}, // - {8100, 17424, 17424, 33124, 33124}}; - - ASSERT_TRUE(all_of(ref == linfdist(ima1, sqr(ima2)))); - - - image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // - {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; - - image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // - {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; - - image2d ref2 = {{6, 0, 6}, // - {6, 0, 6}, // - {6, 0, 6}}; - - ASSERT_TRUE(all_of(ref2 == linfdist(ima3, ima4))); -} diff --git a/tests/core/image/view/maths_components.cpp b/tests/core/image/view/maths_components.cpp new file mode 100644 index 00000000..e7c1ed9f --- /dev/null +++ b/tests/core/image/view/maths_components.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + + +TEST(View, maths_abs) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == abs(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + ASSERT_TRUE(all_of(ref2 == abs(ima2))); +} + +TEST(View, maths_sqr) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + image2d ref = {{0, 1, 4, 9, 16}, // + {25, 36, 16, 64, 81}, // + {100, 121, 144, 169, 196}}; + + ASSERT_TRUE(all_of(ref == sqr(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}}; + + ASSERT_TRUE(all_of(ref2 == sqr(ima2))); +} + +TEST(View, maths_pow) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + auto ima = view::transform(ref, [](auto x) { return x * x * x; }); + + ASSERT_TRUE(all_of(pow(ref, 3) == ima)); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}, // + {{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}, // + {{1, 8, 27}, {64, 125, 216}, {343, 512, 729}}}; + + ASSERT_TRUE(all_of(ref2 == pow(ima2, 3))); +} + +TEST(View, maths_sqrt) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, 1, 4, 9, 16}, // + {25, 36, 16, 64, 81}, // + {100, 121, 144, 169, 196}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == sqrt(ima))); + + + image2d ima2 = {{{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}, // + {{1, 4, 9}, {16, 25, 36}, {49, 64, 81}}}; + + image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + ASSERT_TRUE(all_of(ref2 == sqrt(ima2))); +} + +TEST(View, maths_cbrt) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + auto ima = pow(ref, 3); + + ASSERT_TRUE(all_of(ref == view::cast(cbrt(ima)))); + + + image2d ref2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + auto ima2 = pow(ref2, 3); + + ASSERT_TRUE(all_of(ref2 == view::cast(cbrt(ima2)))); +} diff --git a/tests/core/image/view/maths_distances.cpp b/tests/core/image/view/maths_distances.cpp new file mode 100644 index 00000000..d2c33c4d --- /dev/null +++ b/tests/core/image/view/maths_distances.cpp @@ -0,0 +1,226 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + + +TEST(View, maths_l0dist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == l0dist(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}}; + + image2d ima4 = {{{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}, // + {{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}, // + {{3, 6, 6}, {2, 4, 4}, {1, 2, 2}}}; + + image2d ref2 = {{2, 0, 2}, // + {2, 0, 2}, // + {2, 0, 2}}; + + ASSERT_TRUE(all_of(ref2 == l0dist(ima3, ima4))); +} + +TEST(View, maths_l1dist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == l1dist(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{18, 0, 18}, // + {18, 0, 18}, // + {18, 0, 18}}; + + ASSERT_TRUE(all_of(ref2 == l1dist(ima3, ima4))); +} + +TEST(View, maths_l2dist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == view::cast(l2dist(ima1, sqr(ima2))))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}, // + {{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}, // + {{5, 6, 5}, {4, 5, 6}, {5, 4, 5}}}; + + image2d ref2 = {{6, 0, 6}, // + {6, 0, 6}, // + {6, 0, 6}}; + + ASSERT_TRUE(all_of(ref2 == view::cast(l2dist(ima3, ima4)))); +} + +TEST(View, maths_lpdist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 2, 2, 12, 12}, // + {30, 30, 20, 56, 90}, // + {90, 132, 132, 182, 182}}; + + ASSERT_TRUE(all_of(ref == lpdist<4>(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{1, 1, 1}, // + {1, 1, 1}, // + {1, 1, 1}}; + + ASSERT_TRUE(all_of(ref2 == view::cast(lpdist<4>(ima3, ima4)))); +} + +TEST(View, maths_l2dist_sqr) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 4, 4, 144, 144}, // + {900, 900, 400, 3136, 8100}, // + {8100, 17424, 17424, 33124, 33124}}; + + ASSERT_TRUE(all_of(ref == l2dist_sqr(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{108, 0, 108}, // + {108, 0, 108}, // + {108, 0, 108}}; + + ASSERT_TRUE(all_of(ref2 == l2dist_sqr(ima3, ima4))); +} + +TEST(View, maths_linfdist) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ima2 = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 4, 4, 144, 144}, // + {900, 900, 400, 3136, 8100}, // + {8100, 17424, 17424, 33124, 33124}}; + + ASSERT_TRUE(all_of(ref == linfdist(ima1, sqr(ima2)))); + + + image2d ima3 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima4 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref2 = {{6, 0, 6}, // + {6, 0, 6}, // + {6, 0, 6}}; + + ASSERT_TRUE(all_of(ref2 == linfdist(ima3, ima4))); +} diff --git a/tests/core/image/view/maths_norms.cpp b/tests/core/image/view/maths_norms.cpp new file mode 100644 index 00000000..703256ea --- /dev/null +++ b/tests/core/image/view/maths_norms.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + + +TEST(View, maths_l0norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == l0norm(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{1, 4, 7}, // + {1, 4, 7}, // + {1, 4, 7}}; + + ASSERT_TRUE(all_of(ref2 == l0norm(ima2))); +} + +TEST(View, maths_l1norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == l1norm(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{6, 15, 24}, // + {6, 15, 24}, // + {6, 15, 24}}; + + ASSERT_TRUE(all_of(ref2 == l1norm(ima2))); +} + +TEST(View, maths_l2norm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == l2norm(ima))); + + + image2d ima2 = {{{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}, // + {{1, 2, 2}, {2, 4, 4}, {3, 6, 6}}}; + + image2d ref2 = {{3, 6, 9}, // + {3, 6, 9}, // + {3, 6, 9}}; + + ASSERT_TRUE(all_of(ref2 == l2norm(ima2))); +} + +TEST(View, maths_lpnorm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == lpnorm<4>(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{1, 1, 1}, // + {1, 1, 1}, // + {1, 1, 1}}; + + ASSERT_TRUE(all_of(ref2 == lpnorm<4>(ima2))); +} + +TEST(View, maths_l2norm_sqr) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 4, 9, 16}, // + {25, 36, 16, 64, 81}, // + {100, 121, 144, 169, 196}}; + + ASSERT_TRUE(all_of(ref == l2norm_sqr(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{14, 77, 194}, // + {14, 77, 194}, // + {14, 77, 194}}; + + ASSERT_TRUE(all_of(ref2 == l2norm_sqr(ima2))); +} + +TEST(View, maths_linfnorm) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, 1, 2, 3, 4}, // + {5, 6, 4, 8, 9}, // + {10, 11, 12, 13, 14}}; + + ASSERT_TRUE(all_of(ref == linfnorm(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{3, 6, 9}, // + {3, 6, 9}, // + {3, 6, 9}}; + + ASSERT_TRUE(all_of(ref2 == linfnorm(ima2))); +} diff --git a/tests/core/image/view/maths_reductions.cpp b/tests/core/image/view/maths_reductions.cpp new file mode 100644 index 00000000..920621b6 --- /dev/null +++ b/tests/core/image/view/maths_reductions.cpp @@ -0,0 +1,164 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + + +TEST(View, maths_sum) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == sum(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{6, 15, 24}, // + {6, 15, 24}, // + {6, 15, 24}}; + + ASSERT_TRUE(all_of(ref2 == sum(ima2))); +} + +TEST(View, maths_prod) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == prod(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{6, 120, 504}, // + {6, 120, 504}, // + {6, 120, 504}}; + + ASSERT_TRUE(all_of(ref2 == prod(ima2))); +} + +TEST(View, maths_cross) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima2 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref = {{{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}, // + {{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}, // + {{-6, 12, -6}, {0, 0, 0}, {6, -12, 6}}}; + + ASSERT_TRUE(all_of(ref == cross(ima1, ima2))); +} + +TEST(View, maths_dot) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima1 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ima2 = {{{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}, // + {{7, 8, 9}, {4, 5, 6}, {1, 2, 3}}}; + + image2d ref = {{50, 77, 50}, // + {50, 77, 50}, // + {50, 77, 50}}; + + ASSERT_TRUE(all_of(ref == dot(ima1, ima2))); +} + +TEST(View, maths_min) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == min(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{1, 4, 7}, // + {1, 4, 7}, // + {1, 4, 7}}; + + ASSERT_TRUE(all_of(ref2 == min(ima2))); +} + +TEST(View, maths_max) +{ + using namespace mln; + using namespace view::ops; + using namespace view::maths; + + image2d ima = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + image2d ref = {{0, -1, 2, -3, 4}, // + {-5, 6, -4, 8, -9}, // + {10, -11, 12, -13, 14}}; + + ASSERT_TRUE(all_of(ref == max(ima))); + + + image2d ima2 = {{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, // + {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}}; + + image2d ref2 = {{3, 6, 9}, // + {3, 6, 9}, // + {3, 6, 9}}; + + ASSERT_TRUE(all_of(ref2 == max(ima2))); +} -- GitLab From 668a55e26ffa95725e283d8d711d331574ff859d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Wed, 10 Apr 2019 17:23:33 +0200 Subject: [PATCH 38/61] Add documentation for views : filter, zip, operators, cast, maths TODO : clip, mask, functional maths, others --- doc/source/core.rst | 84 +++---- doc/source/core/functional.rst | 4 + doc/source/core/images.rst | 9 +- doc/source/core/view/cast.rst | 53 ++++ doc/source/core/view/clip.rst | 2 + doc/source/core/view/filter.rst | 55 +++++ doc/source/core/view/mask.rst | 2 + doc/source/core/view/maths.rst | 335 ++++++++++++++++++++++++++ doc/source/core/view/operators.rst | 375 ++++++++++++++++++++++++++++- doc/source/core/view/transform.rst | 44 ++-- doc/source/core/view/zip.rst | 67 ++++++ 11 files changed, 964 insertions(+), 66 deletions(-) create mode 100644 doc/source/core/functional.rst create mode 100644 doc/source/core/view/cast.rst create mode 100644 doc/source/core/view/clip.rst create mode 100644 doc/source/core/view/filter.rst create mode 100644 doc/source/core/view/mask.rst create mode 100644 doc/source/core/view/zip.rst diff --git a/doc/source/core.rst b/doc/source/core.rst index 4a2fbaaa..471aa946 100644 --- a/doc/source/core.rst +++ b/doc/source/core.rst @@ -12,6 +12,7 @@ Core Module core/ranges core/neighborhood core/stl + core/functional @@ -63,18 +64,18 @@ See :doc:`core/images` for a description of the image concepts and image basics. :widths: auto :class: full + +---------------------------------------------------------------+--------------------------------------------------------------------------------------------+ + | :cpp:func:`view::transform(ima, f) ` | Views the image with a function applied to the values. | + +---------------------------------------------------------------+--------------------------------------------------------------------------------------------+ + | :cpp:func:`view::filter(ima, pred) ` | Views the image restricted to pixels whose values pass a predicate. | + +---------------------------------------------------------------+--------------------------------------------------------------------------------------------+ + | :cpp:func:`view::mask(ima, mask) ` | Views the image restricted to pixels in a binary mask. | + +---------------------------------------------------------------+--------------------------------------------------------------------------------------------+ + | :cpp:func:`view::clip(ima, roi) ` | Views the image restricted to a sub-region. | + +---------------------------------------------------------------+--------------------------------------------------------------------------------------------+ + | :cpp:func:`view::zip(ima1, ima2, ..., imaN) ` | Views a list of images as a single image whose values are tuples of the each image values. | + +---------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - +------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | :cpp:func:`view::transform(ima, f) ` | Views the image with a function applied to the values. | - +------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | ``view::filter(ima, pred)`` | Views the image restricted to pixels whose values pass a predicate. | - +------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | ``view::mask(ima, mask)`` | Views the image restricted to pixels in a binary mask. | - +------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | ``view::clip(ima, roi)`` | Views the image restricted to a sub-region. | - +------------------------------------------------------------+--------------------------------------------------------------------------------------------+ - | ``view::zip(ima1, ima2, ..., imaN)`` | Views a list of images as a single image whose values are tuples of the each image values. | - +------------------------------------------------------------+--------------------------------------------------------------------------------------------+ .. topic:: Common image operators (views) @@ -82,32 +83,33 @@ See :doc:`core/images` for a description of the image concepts and image basics. :widths: auto :class: full - +--------------+-----------------------------------------------------------+ - | Arithmetical | `a + b`, `a - b`, `a * b`, `a / b`, `a % b` | - +--------------+-----------------------------------------------------------+ - | Logical | `a && b`, `a || b`, `! a` | - +--------------+-----------------------------------------------------------+ - | Comparison | `a < b`, `a <= b`, `a == b`, `a != b`, `a >= b`, `a > b` | - +--------------+-----------------------------------------------------------+ - | Conditional | ``view::ifelse(a, b, c)`` | - +--------------+-----------------------------------------------------------+ - - Cf. :doc:`core/view/operators` for examples. + +--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Arithmetical | :cpp:func:`a + b `, :cpp:func:`a - b `, :cpp:func:`a * b `, :cpp:func:`a / b `, :cpp:func:`a % b ` | + +--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Logical | :cpp:func:`a && b `, :cpp:func:`a || b `, :cpp:func:`\!a ` | + +--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Comparison | :cpp:func:`a \< b `, :cpp:func:`a \<= b `, :cpp:func:`a == b `, :cpp:func:`a != b `, :cpp:func:`a >= b =>`, :cpp:func:`a > b >` | + +--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Conditional | :cpp:func:`view::ifelse(a, b, c) ` | + +--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ .. topic:: Mathematical image operator (views) - +----------------+---------------------------------------------------------------------------------------------------------+ - | Component-wise | `abs(a)`, `sqr(a)`, `pow(a, p)`, `cbrt(a)`, `sqrt(a)` | - +----------------+---------------------------------------------------------------------------------------------------------+ - | Reduction | `sum(a)`, `prod(a)`, `min(a)`, `max(a)`, `dot(a, b)`, `cross(a, b)` | - +----------------+---------------------------------------------------------------------------------------------------------+ - | Norms | `l0norm(a)`, `l1norm(a)`, `l2norm(a)`, `l2norm_sqr(a)`, `linfnorm(a)`, `lpnorm

(a)` | - +----------------+---------------------------------------------------------------------------------------------------------+ - | Distances | `l0dist(a, b)`, `l1dist(a, b)`, `l2dist(a, b)`, `l2dist_sqr(a, b)`, `linfdist(a, b)`, `lpdist

(a, b)` | - +----------------+---------------------------------------------------------------------------------------------------------+ + .. table:: + :widths: auto + :class: full + + +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Component-wise | :cpp:func:`abs(a) `, :cpp:func:`sqr(a) `, :cpp:func:`pow(a, p) `, :cpp:func:`cbrt(a) `, :cpp:func:`sqrt(a) ` | + +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Reduction | :cpp:func:`sum(a) `, :cpp:func:`prod(a) `, :cpp:func:`min(a) `, :cpp:func:`max(a) `, :cpp:func:`dot(a, b) `, :cpp:func:`cross(a, b) ` | + +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Norms | :cpp:func:`l0norm(a) `, :cpp:func:`l1norm(a) `, :cpp:func:`l2norm(a) `, :cpp:func:`l2norm_sqr(a) `, :cpp:func:`linfnorm(a) `, `lpnorm\

(a) ` | + +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Distances | :cpp:func:`l0dist(a, b) `, :cpp:func:`l1dist(a, b) `, :cpp:func:`l2dist(a, b) `, :cpp:func:`l2dist_sqr(a, b) `, :cpp:func:`linfdist(a, b) `, :cpp:func:`lpdist

(a, b) ` | + +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - Cf. :doc:`core/view/maths` for examples. .. topic:: Other image operators (views) @@ -115,15 +117,15 @@ See :doc:`core/images` for a description of the image concepts and image basics. :widths: auto :class: full - +---------------------------+---------------------------------------------------+ - | ``view::cast(ima)`` | Views the image with the values casted into ``V`` | - +---------------------------+---------------------------------------------------+ - | ``view::channel(ima, k)`` | Views the k-th channel of the image | - +---------------------------+---------------------------------------------------+ - | ``view::red(ima)`` | | - | ``view::green(ima)`` | | - | ``view::blue(ima)`` | Views the red, green or blue channel of the image | - +---------------------------+---------------------------------------------------+ + +---------------------------------------------------+---------------------------------------------------+ + | :cpp:func:`view::cast\(ima) ` | Views the image with the values casted into ``T`` | + +---------------------------------------------------+---------------------------------------------------+ + | ``view::channel(ima, k)`` | Views the k-th channel of the image | + +---------------------------------------------------+---------------------------------------------------+ + | ``view::red(ima)`` | | + | ``view::green(ima)`` | Views the red, green or blue channel of the image | + | ``view::blue(ima)`` | | + +---------------------------------------------------+---------------------------------------------------+ .. raw:: html diff --git a/doc/source/core/functional.rst b/doc/source/core/functional.rst new file mode 100644 index 00000000..4bdc41f8 --- /dev/null +++ b/doc/source/core/functional.rst @@ -0,0 +1,4 @@ +Functional maths operators +########################## + +TODO: document scalar and vec overloads (except for dot and cross: only vec) for each functional maths operators diff --git a/doc/source/core/images.rst b/doc/source/core/images.rst index a0b355b8..06516bb9 100644 --- a/doc/source/core/images.rst +++ b/doc/source/core/images.rst @@ -8,8 +8,15 @@ Forsee to add pdim (point) and vdim (value) for dimension constant in iamge conc .. toctree:: :hidden: - + + view/cast + view/clip + view/filter + view/mask + view/maths + view/operators view/transform + view/zip .. contents:: diff --git a/doc/source/core/view/cast.rst b/doc/source/core/view/cast.rst new file mode 100644 index 00000000..8721bb9b --- /dev/null +++ b/doc/source/core/view/cast.rst @@ -0,0 +1,53 @@ +Cast (View) +########### + +Include :file:`` + +.. cpp:namespace:: mln::view + +#. .. cpp:function:: auto cast(Image ima) + + 1. Makes a view from `ima` where for each pixel value evals to `out(p) = static_cast(ima(p))` + + :param ima: Input range + :tparam T: Type to cast to + + .. code:: + + mln::image2d ima = ...; + auto g1 = mln::view::cast(ima); + ++----------------+---------------+-------+---------------------+ +| | | *ima* | *cast(ima)* | ++================+===============+=======+=====================+ +| | Forward | X | X | ++ +---------------+-------+---------------------+ +| **Category** | Bidirectional | X | X | ++ +---------------+-------+---------------------+ +| | Raw | X | | ++----------------+---------------+-------+---------------------+ +| | Writable | X | | ++ +---------------+-------+---------------------+ +| **Properties** | Accessible | X | X | ++ +---------------+-------+---------------------+ +| | Indexable | X | X | ++----------------+---------------+-------+---------------------+ + + +Examples +-------- + +* Double image to int: + +.. code:: + + mln::image2d input = { {0.1, 1.1, 2.1}, {3.5, 4.5, 5.5} }; + auto g = mln::view::cast(input); + mln::io::imprint(g); + +Outputs: + +.. code-block:: text + + 0 1 2 + 3 4 5 diff --git a/doc/source/core/view/clip.rst b/doc/source/core/view/clip.rst new file mode 100644 index 00000000..7366628e --- /dev/null +++ b/doc/source/core/view/clip.rst @@ -0,0 +1,2 @@ +Clip (View) +########### \ No newline at end of file diff --git a/doc/source/core/view/filter.rst b/doc/source/core/view/filter.rst new file mode 100644 index 00000000..75ce3f68 --- /dev/null +++ b/doc/source/core/view/filter.rst @@ -0,0 +1,55 @@ +Filter (View) +############# + +Include :file:`` + +.. cpp:namespace:: mln::view + +#. .. cpp:function:: auto filter(Image ima, Predicate pred) + + 1. Makes a view where for each pixel is kept if and only if the predicate `pred(ima(p))` is true. + + :param ima: Input range + :param pred: Predicate to apply on pixel values + + .. code:: + + mln::image2d ima = ...; + auto g1 = mln::view::filter(ima, [](int v) { return v > 125; }); + + ++----------------+---------------+-------+---------------------+ +| | | *ima* | *filter(ima, pred)* | ++================+===============+=======+=====================+ +| | Forward | X | X | ++ +---------------+-------+---------------------+ +| **Category** | Bidirectional | X | X | ++ +---------------+-------+---------------------+ +| | Raw | X | | ++----------------+---------------+-------+---------------------+ +| | Writable | X | | ++ +---------------+-------+---------------------+ +| **Properties** | Accessible | X | X | ++ +---------------+-------+---------------------+ +| | Indexable | X | X | ++----------------+---------------+-------+---------------------+ + +(*): only if `f` is a projection. + + +Examples +-------- + +* Keep all add values: + +.. code:: + + mln::image2d input = { {0, 1, 2}, {3, 4, 5} }; + auto g = mln::view::transform(input, [](int v) { return v % 2 != 0; }); + mln::io::imprint(g); + +Outputs: + +.. code-block:: text + 0 1 + 3 5 diff --git a/doc/source/core/view/mask.rst b/doc/source/core/view/mask.rst new file mode 100644 index 00000000..9d568066 --- /dev/null +++ b/doc/source/core/view/mask.rst @@ -0,0 +1,2 @@ +Mask (View) +########### \ No newline at end of file diff --git a/doc/source/core/view/maths.rst b/doc/source/core/view/maths.rst index 66235ace..4f1615a8 100644 --- a/doc/source/core/view/maths.rst +++ b/doc/source/core/view/maths.rst @@ -1,4 +1,339 @@ Maths (view) ############ +Include :file:`` +.. cpp:namespace:: mln::view::maths + +Component-wise +============== + + +#. .. cpp:function:: auto abs(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = abs(ima(p))`. Cf. :cpp:func:`abs ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::abs(ima); + + +#. .. cpp:function:: auto pow(Image ima, Scalar s) + + 1. Makes a view where for each pixel value evals to `out(p) = pow(ima(p), s)`. Cf. :cpp:func:`pow ` documentaion. + + :param ima: Input range + :param s: Exponent + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::pow(ima, 3); + + +#. .. cpp:function:: auto sqr(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = sqr(ima(p))`. Cf. :cpp:func:`sqr ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::sqr(ima); + + +#. .. cpp:function:: auto cbrt(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = cbrt(ima(p))`. Cf. :cpp:func:`cbrt ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::cbrt(ima); + + +#. .. cpp:function:: auto sqrt(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = sqrt(ima(p))`. Cf. :cpp:func:`sqrt ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::sqrt(ima); + + +Reduction +========= + + +#. .. cpp:function:: auto sum(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = sum(ima(p))`. Cf. :cpp:func:`sum ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::sum(ima); + + +#. .. cpp:function:: auto prod(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = prod(ima(p))`. Cf. :cpp:func:`prod ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::prod(ima); + + +#. .. cpp:function:: auto min(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = min(ima(p))`. Cf. :cpp:func:`min ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::min(ima); + + +#. .. cpp:function:: auto max(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = max(ima(p))`. Cf. :cpp:func:`max ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::max(ima); + + +#. .. cpp:function:: auto dot(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = dot(ima1(p), ima2(p))`. Cf. :cpp:func:`dot ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::dot(ima1, ima2); + + +#. .. cpp:function:: auto cross(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = cross(ima1(p), ima2(p))`. Cf. :cpp:func:`cross ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::cross(ima1, ima2); + + +Norms +===== + + +#. .. cpp:function:: auto l0norm(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = l0norm(ima(p))`. Cf. :cpp:func:`l0norm ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::l0norm(ima); + + +#. .. cpp:function:: auto l1norm(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = l1norm(ima(p))`. Cf. :cpp:func:`l1norm ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::l1norm(ima); + + +#. .. cpp:function:: auto l2norm(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = l2norm(ima(p))`. Cf. :cpp:func:`l2norm ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::l2norm(ima); + + +#. .. cpp:function:: auto l2norm_sqr(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = l2norm_sqr(ima(p))`. Cf. :cpp:func:`l2norm_sqr ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::l2norm_sqr(ima); + + +#. .. cpp:function:: auto linfnorm(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = linfnorm(ima(p))`. Cf. :cpp:func:`linfnorm ` documentaion. + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::linfnorm(ima); + + +#. .. cpp:function:: template auto lpnorm(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = lpnorm(ima(p))`. Cf. :cpp:func:`lpnorm ` documentaion. + + :param ima: Input range + :tparam V: Norm exponent + + .. code:: + + mln::image2d ima = ...; + mln::image2d g = mln::view::maths::lpnorm<4>(ima); + + + +Distances +========= + + +#. .. cpp:function:: auto l0dist(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = l0dist(ima1, ima2)`. Cf. :cpp:func:`l0dist ` documentaion. + + :param ima1: Input range + :param ima2: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::l0dist(ima1, ima2); + + +#. .. cpp:function:: auto l1dist(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = l1dist(ima1, ima2)`. Cf. :cpp:func:`l1dist ` documentaion. + + :param ima1: Input range + :param ima2: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::l1dist(ima1, ima2); + + +#. .. cpp:function:: auto l2dist(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = l2dist(ima1, ima2)`. Cf. :cpp:func:`l2dist ` documentaion. + + :param ima1: Input range + :param ima2: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::l2dist(ima1, ima2); + + +#. .. cpp:function:: auto l2dist_sqr(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = l2dist_sqr(ima1, ima2)`. Cf. :cpp:func:`l2dist_sqr ` documentaion. + + :param ima1: Input range + :param ima2: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::l2dist_sqr(ima1, ima2); + + + +#. .. cpp:function:: auto lindist(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = linfdist(ima1, ima2)`. Cf. :cpp:func:`linfdist ` documentaion. + + :param ima1: Input range + :param ima2: Input range + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::linfdist(ima1, ima2); + + +#. .. cpp:function:: template auto lpdist(Image ima1, Image ima2) + + 1. Makes a view where for each pixel value evals to `out(p) = lpdist(ima1(p), ima2(p))`. Cf. :cpp:func:`lpdist ` documentaion. + + :param ima1: Input range + :param ima2: Input range + :tparam V: Norm Exponent + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d g = mln::view::maths::lpdist<4>(ima1, ima2); + + ++----------------+---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | | *ima, ima1, ima2* | *abs, pow, sqr, cbrt, sqrt, sum, prod, min, max, dot, cross, l0norm, l1norm, l2norm, l2norm_sqr, linfnorm, lpnorm, l0dist, l1dist, l2dist, l2dist_sqr, linfdist, lpdist* | ++================+===============+===================+==========================================================================================================================================================================+ +| | Forward | X | X | ++ +---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Category** | Bidirectional | X | X | ++ +---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Raw | X | | ++----------------+---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Writable | X | | ++ +---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Properties** | Accessible | X | X | ++ +---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| | Indexable | X | X | ++----------------+---------------+-------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +Examples +-------- + +TODO \ No newline at end of file diff --git a/doc/source/core/view/operators.rst b/doc/source/core/view/operators.rst index 30404ce4..d6149e2a 100644 --- a/doc/source/core/view/operators.rst +++ b/doc/source/core/view/operators.rst @@ -1 +1,374 @@ -TODO \ No newline at end of file +Operators (View) +################ + +Include :file:`` + +.. cpp:namespace:: mln::view::ops + + +Arithmetical +============ + + +#. .. cpp:function:: auto operator+(Image ima1, Image ima2) +#. .. cpp:function:: auto operator+(Image ima1, Scalar s) +#. .. cpp:function:: auto operator+(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) + ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) + s`. + 3. Makes a view where for each pixel value evals to `out(p) = s + ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 + ima2; + double s = 5.5; + auto g1 = ima1 + s; + auto g1 = s + ima1; + + +#. .. cpp:function:: auto operator-(Image ima1, Image ima2) +#. .. cpp:function:: auto operator-(Image ima1, Scalar s) +#. .. cpp:function:: auto operator-(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) - ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) - s`. + 3. Makes a view where for each pixel value evals to `out(p) = s - ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 - ima2; + double s = 5.5; + auto g1 = ima1 - s; + auto g1 = s - ima1; + + +#. .. cpp:function:: auto operator*(Image ima1, Image ima2) +#. .. cpp:function:: auto operator*(Image ima1, Scalar s) +#. .. cpp:function:: auto operator*(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) * ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) * s`. + 3. Makes a view where for each pixel value evals to `out(p) = s * ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 * ima2; + double s = 5.5; + auto g1 = ima1 * s; + auto g1 = s * ima1; + + +#. .. cpp:function:: auto operator/(Image ima1, Image ima2) +#. .. cpp:function:: auto operator/(Image ima1, Scalar s) +#. .. cpp:function:: auto operator/(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) / ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) / s`. + 3. Makes a view where for each pixel value evals to `out(p) = s / ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + +.. warning:: Mind the division by zero. + + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 / ima2; + double s = 5.5; + auto g1 = ima1 / s; + auto g1 = s / ima1; + + +#. .. cpp:function:: auto operator%(Image ima1, Image ima2) +#. .. cpp:function:: auto operator%(Image ima1, Scalar s) +#. .. cpp:function:: auto operator%(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) % ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) % s`. + 3. Makes a view where for each pixel value evals to `out(p) = s % ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 % ima2; + double s = 5.5; + auto g1 = ima1 % s; + auto g1 = s % ima1; + + +Logical +======= + + +#. .. cpp:function:: auto operator&&(Image ima1, Image ima2) +#. .. cpp:function:: auto operator&&(Image ima1, Scalar s) +#. .. cpp:function:: auto operator&&(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) && ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) && s`. + 3. Makes a view where for each pixel value evals to `out(p) = s && ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 && ima2; + double s = 5.5; + auto g1 = ima1 && s; + auto g1 = s && ima1; + + +#. .. cpp:function:: auto operator||(Image ima1, Image ima2) +#. .. cpp:function:: auto operator||(Image ima1, Scalar s) +#. .. cpp:function:: auto operator||(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) || ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) || s`. + 3. Makes a view where for each pixel value evals to `out(p) = s || ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 || ima2; + double s = 5.5; + auto g1 = ima1 || s; + auto g1 = s || ima1; + + +#. .. cpp:function:: auto operator!(Image ima) + + 1. Makes a view where for each pixel value evals to `out(p) = !ima(p)` + + :param ima: Input range + + .. code:: + + mln::image2d ima = ...; + auto g = !ima; + + +Comparison +========== + + +#. .. cpp:function:: auto operator<(Image ima1, Image ima2) +#. .. cpp:function:: auto operator<(Image ima1, Scalar s) +#. .. cpp:function:: auto operator<(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) < ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) < s`. + 3. Makes a view where for each pixel value evals to `out(p) = s < ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 < ima2; + double s = 5.5; + auto g1 = ima1 < s; + auto g1 = s < ima1; + + +#. .. cpp:function:: auto operator<=(Image ima1, Image ima2) +#. .. cpp:function:: auto operator<=(Image ima1, Scalar s) +#. .. cpp:function:: auto operator<=(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) <= ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) <= s`. + 3. Makes a view where for each pixel value evals to `out(p) = s <= ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 <= ima2; + double s = 5.5; + auto g1 = ima1 <= s; + auto g1 = s <= ima1; + + +#. .. cpp:function:: auto operator==(Image ima1, Image ima2) +#. .. cpp:function:: auto operator==(Image ima1, Scalar s) +#. .. cpp:function:: auto operator==(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) == ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) == s`. + 3. Makes a view where for each pixel value evals to `out(p) = s == ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 == ima2; + double s = 5.5; + auto g1 = ima1 == s; + auto g1 = s == ima1; + + +#. .. cpp:function:: auto operator!=(Image ima1, Image ima2) +#. .. cpp:function:: auto operator!=(Image ima1, Scalar s) +#. .. cpp:function:: auto operator!=(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) != ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) != s`. + 3. Makes a view where for each pixel value evals to `out(p) = s != ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 != ima2; + double s = 5.5; + auto g1 = ima1 != s; + auto g1 = s != ima1; + + +#. .. cpp:function:: auto operator>(Image ima1, Image ima2) +#. .. cpp:function:: auto operator>(Image ima1, Scalar s) +#. .. cpp:function:: auto operator>(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) > ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) > s`. + 3. Makes a view where for each pixel value evals to `out(p) = s > ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 > ima2; + double s = 5.5; + auto g1 = ima1 > s; + auto g1 = s > ima1; + + +#. .. cpp:function:: auto operator>=(Image ima1, Image ima2) +#. .. cpp:function:: auto operator>=(Image ima1, Scalar s) +#. .. cpp:function:: auto operator>=(Scalar s, Image ima1) + + 1. Makes a view where for each pixel value evals to `out(p) = ima1(p) >= ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima1(p) >= s`. + 3. Makes a view where for each pixel value evals to `out(p) = s >= ima1(p)`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = ima1 >= ima2; + double s = 5.5; + auto g1 = ima1 >= s; + auto g1 = s >= ima1; + + +.. cpp:namespace:: mln::view + +Conditional +=========== + + +#. .. cpp:function:: auto ifelse(Image ima, Image ima1, Image ima2) +#. .. cpp:function:: auto ifelse(Image ima, Image ima1, Scalar s_else) +#. .. cpp:function:: auto ifelse(Image ima, Scalar s_if, Image ima2) +#. .. cpp:function:: auto ifelse(Image ima, Scalar s_if, Scalar s_else) + + 1. Makes a view where for each pixel value evals to `out(p) = ima(p) ? ima1(p) : ima2(p)` + 2. Makes a view where for each pixel value evals to `out(p) = ima(p) ? ima1(p) : s_else`. + 3. Makes a view where for each pixel value evals to `out(p) = ima(p) ? s_if : ima2(p)`. + 3. Makes a view where for each pixel value evals to `out(p) = ima(p) ? s_if : s_else`. + + :param ima1: Input range + :param ima2: Input range + :param s: Scalar value + + .. code:: + + mln::image2d ima = ...; + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + auto g1 = view::ifelse(ima == 0, ima1, ima2); + auto g2 = view::ifelse(ima < 125, 125, ima); + auto g3 = view::ifelse(ima > 125, ima, 125); + auto g4 = view::ifelse(ima < 125, 0, 255); + + ++----------------+---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ +| | | *ima, ima2* | *+, -, *, /, %, <, <=, ==, !=, >, >=* | *ifelse(ima, ima1, ima2)* | *ifelse(ima, ima1, s_else) / ifelse(ima, s_if, ima2) / ifelse(ima, s_if, s_else)* | ++================+===============+=============+=======================================+===========================+=====================================================================================+ +| | Forward | X | X | X | X | ++ +---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ +| **Category** | Bidirectional | X | X | X | X | ++ +---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ +| | Raw | X | | | | ++----------------+---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ +| | Writable | X | | X | | ++ +---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ +| **Properties** | Accessible | X | X | X | X | ++ +---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ +| | Indexable | X | X | X | X | ++----------------+---------------+-------------+---------------------------------------+---------------------------+-------------------------------------------------------------------------------------+ + + +Examples +-------- + +TODO diff --git a/doc/source/core/view/transform.rst b/doc/source/core/view/transform.rst index 008b0507..e04e6d19 100644 --- a/doc/source/core/view/transform.rst +++ b/doc/source/core/view/transform.rst @@ -11,15 +11,14 @@ Include :file:`` 1. Makes a view from `ima` where for each pixel value evals to `out(p) = f(ima(p))` 2. Makes a view from `ima` where for each pixel value evals to `out(p) = f(ima(p), ima2(p))`. For this overload, the domain of both image must be equal. - :param ima: Input range :param ima2: Input range :param f: Function to apply on pixel values - .. warning:: The function f must not create dangling references on the input. + .. code:: mln::image2d ima = ...; @@ -27,23 +26,21 @@ Include :file:`` auto g2 = mln::view::transform(g1, [](const rgb8& v) -> const uint8& { return v[0]; }); // KO: create a dangling reference to g1(p) - -+----------------+---------------+------------+---------------------+---------------------------+ -| | | *ima,ima2* | *transform(ima, f)* | *transform(ima, ima2, f)* | -+================+===============+============+=====================+===========================+ -| | Forward | X | X | X | -+ +---------------+------------+---------------------+---------------------------+ -| **Category** | Bidirectional | X | X | X | -+ +---------------+------------+---------------------+---------------------------+ -| | Raw | X | | | -+----------------+---------------+------------+---------------------+---------------------------+ -| | Writable | X | X* | X* | -+ +---------------+------------+---------------------+---------------------------+ -| **Properties** | Accessible | X | X | X | -+ +---------------+------------+---------------------+---------------------------+ -| | Indexable | X | X | X | -+----------------+---------------+------------+---------------------+---------------------------+ - ++----------------+---------------+-------------+---------------------+---------------------------+ +| | | *ima, ima2* | *transform(ima, f)* | *transform(ima, ima2, f)* | ++================+===============+=============+=====================+===========================+ +| | Forward | X | X | X | ++ +---------------+-------------+---------------------+---------------------------+ +| **Category** | Bidirectional | X | X | X | ++ +---------------+-------------+---------------------+---------------------------+ +| | Raw | X | | | ++----------------+---------------+-------------+---------------------+---------------------------+ +| | Writable | X | X* | X* | ++ +---------------+-------------+---------------------+---------------------------+ +| **Properties** | Accessible | X | X | X | ++ +---------------+-------------+---------------------+---------------------------+ +| | Indexable | X | X | X | ++----------------+---------------+-------------+---------------------+---------------------------+ (*): only if `f` is a projection. @@ -55,7 +52,7 @@ Examples .. code:: - mln::image2d input = { {0,1,2}, {3,4,5} }; + mln::image2d input = { {0, 1, 2}, {3, 4, 5} }; auto g = mln::view::transform(input, [](mln::uint8 v) { return v * 2; }); mln::io::imprint(g); @@ -70,9 +67,10 @@ Outputs: .. code:: - mln::image2d input = {{{0,0,0}, {1,1,1}, {2,2,2}}, {{3,3,3}, {4,4,4}, {5,5,5}}}; + mln::image2d input = {{{0, 0, 0}, {1, 1, 1}, {2, 2, 2}}, {{3, 3, 3}, {4, 4, 4}, {5, 5, 5}}}; auto g = mln::view::transform(input, [](mln::rgb8& x) -> uint8_t& { return x[0]; }); mln::fill(g, 42); + mln::io::imprint(g); Outputs: @@ -86,7 +84,7 @@ Outputs: .. code-block:: cpp - mln::image2d input1 = ...; - mln::image2d input2 = ...; + mln::image2d input1 = ...; + mln::image2d input2 = ...; auto f = [](uint8_t x, uint8_t y) { return alpha * x + (1 - alpha) * y; }; auto g = mln::view::transform(input1, input2, f); diff --git a/doc/source/core/view/zip.rst b/doc/source/core/view/zip.rst new file mode 100644 index 00000000..2921e9ba --- /dev/null +++ b/doc/source/core/view/zip.rst @@ -0,0 +1,67 @@ +Zip (View) +########## + +Include :file:`` + +.. cpp:namespace:: mln::view + +#. .. cpp:function:: auto zip(Image... ima) + + 1. Makes a view from `ima` where for each pixel value evals to `out(p) = std::make_tuple(ima(p)...)` + + :param ima: Input ranges + + .. code:: + + mln::image2d ima1 = ...; + mln::image2d ima2 = ...; + mln::image2d ima3 = ...; + auto g = mln::view::zip(ima1, ima2, ima3); + + ++----------------+---------------+----------+---------------+ +| | | *ima...* | *zip(ima...)* | ++================+===============+==========+===============+ +| | Forward | X | X | ++ +---------------+----------+---------------+ +| **Category** | Bidirectional | X | X | ++ +---------------+----------+---------------+ +| | Raw | X | | ++----------------+---------------+----------+---------------+ +| | Writable | X | X | ++ +---------------+----------+---------------+ +| **Properties** | Accessible | X | X | ++ +---------------+----------+---------------+ +| | Indexable | X | X | ++----------------+---------------+----------+---------------+ + + +Examples +-------- + +* Traversing both input and output image at the same time: + +.. code:: + + mln::image2d input = { {0, 1, 2}, {3, 4, 5} }; + mln::image2d output{input.domain()}; + mln::fill(output, 0); + auto zipped_ima = mln::view::zip(input, output); + for (auto&& [v_in, v_out] : zipped_ima.values()) + v_out = v_in * v_in; + + auto vals = zipped_ima.values(); + for (auto r : mln::ranges::rows(vals)) + { + for (auto&& [_, v_out] : r) + std::cout << v_out << " "; + std::cout << std::endl; + } + + +Outputs: + +.. code-block:: text + + 0 1 4 + 9 16 25 -- GitLab From 8e51105dc058b3ac4e899b5a9bb4495706ccfe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Roynard?= Date: Thu, 11 Apr 2019 11:31:16 +0200 Subject: [PATCH 39/61] Minor fixes --- doc/source/core.rst | 36 +++++++++++++++--------------- doc/source/core/view/cast.rst | 2 +- doc/source/core/view/filter.rst | 1 + doc/source/core/view/maths.rst | 2 +- doc/source/core/view/operators.rst | 35 ++++++++++++++++++++++++++--- 5 files changed, 53 insertions(+), 23 deletions(-) diff --git a/doc/source/core.rst b/doc/source/core.rst index 471aa946..b102dfc4 100644 --- a/doc/source/core.rst +++ b/doc/source/core.rst @@ -100,15 +100,15 @@ See :doc:`core/images` for a description of the image concepts and image basics. :widths: auto :class: full - +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Component-wise | :cpp:func:`abs(a) `, :cpp:func:`sqr(a) `, :cpp:func:`pow(a, p) `, :cpp:func:`cbrt(a) `, :cpp:func:`sqrt(a) ` | - +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Reduction | :cpp:func:`sum(a) `, :cpp:func:`prod(a) `, :cpp:func:`min(a) `, :cpp:func:`max(a) `, :cpp:func:`dot(a, b) `, :cpp:func:`cross(a, b) ` | - +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Norms | :cpp:func:`l0norm(a) `, :cpp:func:`l1norm(a) `, :cpp:func:`l2norm(a) `, :cpp:func:`l2norm_sqr(a) `, :cpp:func:`linfnorm(a) `, `lpnorm\

(a) ` | - +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - | Distances | :cpp:func:`l0dist(a, b) `, :cpp:func:`l1dist(a, b) `, :cpp:func:`l2dist(a, b) `, :cpp:func:`l2dist_sqr(a, b) `, :cpp:func:`linfdist(a, b) `, :cpp:func:`lpdist

(a, b) ` | - +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Component-wise | :cpp:func:`abs(a) `, :cpp:func:`sqr(a) `, :cpp:func:`pow(a, p) `, :cpp:func:`cbrt(a) `, :cpp:func:`sqrt(a) ` | + +----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Reduction | :cpp:func:`sum(a) `, :cpp:func:`prod(a) `, :cpp:func:`min(a) `, :cpp:func:`max(a) `, :cpp:func:`dot(a, b) `, :cpp:func:`cross(a, b) ` | + +----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + | Norms | :cpp:func:`l0norm(a) `, :cpp:func:`l1norm(a) `, :cpp:func:`l2norm(a) `, :cpp:func:`l2norm_sqr(a) `, :cpp:func:`linfnorm(a) `, :cpp:func:`lpnorm\

(a)