Commit f8418b19 authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Remove the build-pylene target

Pylene lib build is standalone w.r.t to the master-project build.
parent e4dca3a3
......@@ -50,7 +50,7 @@ build-docker-automatic:
- conan install .. -pr pylene_default --build missing -e CXX=g++ -e CC=gcc
- cmake -G Ninja .. -DCMAKE_BUILD_TYPE=$PYLENE_CONFIGURATION -DPYLENE_CODE_COVERAGE=OFF -DSANITIZE_ADDRESS=$ASAN -DSANITIZE_MEMORY=$MSAN -DSANITIZE_UNDEFINED=$UBSAN $OTHER_CMAKE_ARGS
- cmake --build . --target build-fixtures --config $PYLENE_CONFIGURATION
- cmake --build . --target build-pylene --config $PYLENE_CONFIGURATION
- cmake --build . --target Pylene --config $PYLENE_CONFIGURATION
- cmake --build . --target build-apps --config $PYLENE_CONFIGURATION
- cmake --build . --target build-cli --config $PYLENE_CONFIGURATION
- cmake --build . --target build-tests --config $PYLENE_CONFIGURATION
......@@ -69,7 +69,7 @@ build-docker-automatic:
- conan install .. -pr pylene_default --build missing -e CXX=g++ -e CC=gcc
- cmake -G Ninja .. -DCMAKE_BUILD_TYPE=$PYLENE_CONFIGURATION -DPYLENE_CODE_COVERAGE=ON -DGCOV_PATH=$COV -DSANITIZE_ADDRESS=$ASAN -DSANITIZE_MEMORY=$MSAN -DSANITIZE_UNDEFINED=$UBSAN $OTHER_CMAKE_ARGS
- cmake --build . --target build-fixtures --config $PYLENE_CONFIGURATION
- cmake --build . --target build-pylene --config $PYLENE_CONFIGURATION
- cmake --build . --target Pylene --config $PYLENE_CONFIGURATION
- cmake --build . --target build-apps --config $PYLENE_CONFIGURATION
- cmake --build . --target build-cli --config $PYLENE_CONFIGURATION
- cmake --build . --target build-tests --config $PYLENE_CONFIGURATION
......@@ -94,30 +94,30 @@ build-docker-automatic:
# Asan and ubsan can work together
distcheck-linux-gcc8-release:
<<: *distcheck-linux-base
image: ${FEDORA_29}
variables:
PYLENE_CONFIGURATION: "Release"
CXX: "g++"
CC: "gcc"
ASAN: "OFF"
MSAN: "OFF"
UBSAN: "OFF"
OTHER_CMAKE_ARGS: "-DCMAKE_CXX_EXTENSIONS=OFF" # This fixes a GCC ICE
distcheck-linux-gcc8-debug-cov-asan-ubsan:
<<: *distcheck-linux-coverage
image: ${FEDORA_29}
variables:
PYLENE_CONFIGURATION: "Debug"
CXX: "g++"
CC: "gcc"
COV: "/usr/bin/gcov"
ASAN: "ON"
MSAN: "OFF"
UBSAN: "ON"
OTHER_CMAKE_ARGS: "-DCMAKE_CXX_EXTENSIONS=OFF" # This fixes a GCC ICE
# distcheck-linux-gcc8-release:
# <<: *distcheck-linux-base
# image: ${FEDORA_29}
# variables:
# PYLENE_CONFIGURATION: "Release"
# CXX: "g++"
# CC: "gcc"
# ASAN: "OFF"
# MSAN: "OFF"
# UBSAN: "OFF"
# OTHER_CMAKE_ARGS: "-DCMAKE_CXX_EXTENSIONS=OFF" # This fixes a GCC ICE
# distcheck-linux-gcc8-debug-cov-asan-ubsan:
# <<: *distcheck-linux-coverage
# image: ${FEDORA_29}
# variables:
# PYLENE_CONFIGURATION: "Debug"
# CXX: "g++"
# CC: "gcc"
# COV: "/usr/bin/gcov"
# ASAN: "ON"
# MSAN: "OFF"
# UBSAN: "ON"
# OTHER_CMAKE_ARGS: "-DCMAKE_CXX_EXTENSIONS=OFF" # This fixes a GCC ICE
distcheck-linux-gcc9-release:
<<: *distcheck-linux-base
......@@ -144,55 +144,55 @@ distcheck-linux-gcc9-debug-cov-asan-ubsan:
UBSAN: "ON"
OTHER_CMAKE_ARGS: "-DCMAKE_CXX_EXTENSIONS=OFF" # This fixes a GCC ICE
distcheck-linux-clang7-release:
<<: *distcheck-linux-base
image: ${FEDORA_29}
variables:
PYLENE_CONFIGURATION: "Release"
CXX: "clang++"
CC: "clang"
ASAN: "OFF"
MSAN: "OFF"
UBSAN: "OFF"
OTHER_CMAKE_ARGS: ""
distcheck-linux-clang7-debug-cov-asan-ubsan:
<<: *distcheck-linux-coverage
image: ${FEDORA_29}
variables:
PYLENE_CONFIGURATION: "Debug"
CXX: "clang++"
CC: "clang"
COV: "/usr/local/bin/llvm/gcov"
ASAN: "ON"
MSAN: "OFF"
UBSAN: "ON"
OTHER_CMAKE_ARGS: ""
distcheck-linux-clang8-release:
<<: *distcheck-linux-base
image: ${FEDORA_30}
variables:
PYLENE_CONFIGURATION: "Release"
CXX: "clang++"
CC: "clang"
ASAN: "OFF"
MSAN: "OFF"
UBSAN: "OFF"
OTHER_CMAKE_ARGS: ""
distcheck-linux-clang8-debug-cov-asan-ubsan:
<<: *distcheck-linux-coverage
image: ${FEDORA_30}
variables:
PYLENE_CONFIGURATION: "Debug"
CXX: "clang++"
CC: "clang"
COV: "/usr/local/bin/llvm/gcov"
ASAN: "ON"
MSAN: "OFF"
UBSAN: "ON"
OTHER_CMAKE_ARGS: ""
# distcheck-linux-clang7-release:
# <<: *distcheck-linux-base
# image: ${FEDORA_29}
# variables:
# PYLENE_CONFIGURATION: "Release"
# CXX: "clang++"
# CC: "clang"
# ASAN: "OFF"
# MSAN: "OFF"
# UBSAN: "OFF"
# OTHER_CMAKE_ARGS: ""
# distcheck-linux-clang7-debug-cov-asan-ubsan:
# <<: *distcheck-linux-coverage
# image: ${FEDORA_29}
# variables:
# PYLENE_CONFIGURATION: "Debug"
# CXX: "clang++"
# CC: "clang"
# COV: "/usr/local/bin/llvm/gcov"
# ASAN: "ON"
# MSAN: "OFF"
# UBSAN: "ON"
# OTHER_CMAKE_ARGS: ""
# distcheck-linux-clang8-release:
# <<: *distcheck-linux-base
# image: ${FEDORA_30}
# variables:
# PYLENE_CONFIGURATION: "Release"
# CXX: "clang++"
# CC: "clang"
# ASAN: "OFF"
# MSAN: "OFF"
# UBSAN: "OFF"
# OTHER_CMAKE_ARGS: ""
# distcheck-linux-clang8-debug-cov-asan-ubsan:
# <<: *distcheck-linux-coverage
# image: ${FEDORA_30}
# variables:
# PYLENE_CONFIGURATION: "Debug"
# CXX: "clang++"
# CC: "clang"
# COV: "/usr/local/bin/llvm/gcov"
# ASAN: "ON"
# MSAN: "OFF"
# UBSAN: "ON"
# OTHER_CMAKE_ARGS: ""
#########
......
......@@ -94,7 +94,6 @@ endif ()
#### Configuration of the Compiler ###
# Subdirectories
add_custom_target(build-pylene)
add_subdirectory(pylene)
if (NOT PYLENE_BUILD_LIBS_ONLY)
......
......@@ -5,10 +5,11 @@
#define BOOST_CONCEPT_ASSERT(Model)
#include <boost/concept_check.hpp>
#include <mln/core/grays.hpp>
#include <mln/core/image/image2d.hpp>
#include <mln/core/neighb2d.hpp>
#include <mln/core/wrt_offset.hpp>
#include <mln/core/grays.hpp>
#include <benchmark/benchmark.h>
......
#include <mln/core/image/image2d.hpp>
#include <mln/core/image/experimental/ndimage.hpp>
#include <mln/core/rangev3/foreach.hpp>
#include <mln/core/rangev3/rows.hpp>
#include <mln/core/rangev3/view/reverse.hpp>
......@@ -15,7 +16,7 @@ void Mult_Inplace_Reversed(mln::image2d<mln::uint8>& img)
}
}
void Mult_Inplace_New_Values_Reversed(mln::image2d<mln::uint8>& img)
void Mult_Inplace_New_Values_Reversed(mln::experimental::image2d<mln::uint8>& img)
{
auto reversed_values = mln::ranges::view::reverse(img.new_values());
mln_foreach_new (auto& v, reversed_values)
......@@ -24,7 +25,7 @@ void Mult_Inplace_New_Values_Reversed(mln::image2d<mln::uint8>& img)
}
}
void Mult_Inplace_New_Pixels_Reversed(mln::image2d<mln::uint8>& img)
void Mult_Inplace_New_Pixels_Reversed(mln::experimental::image2d<mln::uint8>& img)
{
auto reversed_pixels = mln::ranges::view::reverse(img.new_pixels());
mln_foreach_new (auto&& px, reversed_pixels)
......@@ -68,7 +69,7 @@ void Mult_C_Reversed(const mln::uint8* __restrict__ ibuffer, mln::uint8* __restr
}
}
void Mult_New_Values_Reversed(const mln::image2d<mln::uint8>& input, mln::image2d<mln::uint8>& output)
void Mult_New_Values_Reversed(const mln::experimental::image2d<mln::uint8>& input, mln::experimental::image2d<mln::uint8>& output)
{
auto zipped_values = mln::ranges::view::zip(mln::ranges::view::reverse(input.new_values()),
mln::ranges::view::reverse(output.new_values()));
......@@ -81,7 +82,7 @@ void Mult_New_Values_Reversed(const mln::image2d<mln::uint8>& input, mln::image2
}
}
void Mult_New_Pixels_Reversed(const mln::image2d<mln::uint8>& input, mln::image2d<mln::uint8>& output)
void Mult_New_Pixels_Reversed(const mln::experimental::image2d<mln::uint8>& input, mln::experimental::image2d<mln::uint8>& output)
{
auto zipped_pixels = mln::ranges::view::zip(mln::ranges::view::reverse(input.new_pixels()),
mln::ranges::view::reverse(output.new_pixels()));
......@@ -104,7 +105,7 @@ void Threshold_Inplace_Reversed(mln::image2d<mln::uint8>& img)
}
}
void Threshold_Inplace_New_Values_Reversed(mln::image2d<mln::uint8>& img)
void Threshold_Inplace_New_Values_Reversed(mln::experimental::image2d<mln::uint8>& img)
{
constexpr mln::uint8 t = 128;
......@@ -115,7 +116,7 @@ void Threshold_Inplace_New_Values_Reversed(mln::image2d<mln::uint8>& img)
}
}
void Threshold_Inplace_New_Pixels_Reversed(mln::image2d<mln::uint8>& img)
void Threshold_Inplace_New_Pixels_Reversed(mln::experimental::image2d<mln::uint8>& img)
{
constexpr mln::uint8 t = 128;
......@@ -166,7 +167,7 @@ void Threshold_Reversed(const mln::image2d<mln::uint8>& in, mln::image2d<mln::ui
}
}
void Threshold_New_Values_Reversed(const mln::image2d<mln::uint8>& input, mln::image2d<mln::uint8>& output)
void Threshold_New_Values_Reversed(const mln::experimental::image2d<mln::uint8>& input, mln::experimental::image2d<mln::uint8>& output)
{
constexpr mln::uint8 t = 128;
......@@ -181,7 +182,7 @@ void Threshold_New_Values_Reversed(const mln::image2d<mln::uint8>& input, mln::i
}
}
void Threshold_New_Pixels_Reversed(const mln::image2d<mln::uint8>& input, mln::image2d<mln::uint8>& output)
void Threshold_New_Pixels_Reversed(const mln::experimental::image2d<mln::uint8>& input, mln::experimental::image2d<mln::uint8>& output)
{
constexpr mln::uint8 t = 128;
......@@ -205,7 +206,7 @@ void LUT_Inplace_Reversed(const mln::uint8 LUT[], mln::image2d<mln::uint8>& img)
}
}
void LUT_Inplace_New_Values_Reversed(const mln::uint8 LUT[], mln::image2d<mln::uint8>& img)
void LUT_Inplace_New_Values_Reversed(const mln::uint8 LUT[], mln::experimental::image2d<mln::uint8>& img)
{
mln_foreach_new (auto& v, img.new_values())
{
......@@ -213,7 +214,7 @@ void LUT_Inplace_New_Values_Reversed(const mln::uint8 LUT[], mln::image2d<mln::u
}
}
void LUT_Inplace_New_Pixels_Reversed(const mln::uint8 LUT[], mln::image2d<mln::uint8>& img)
void LUT_Inplace_New_Pixels_Reversed(const mln::uint8 LUT[], mln::experimental::image2d<mln::uint8>& img)
{
mln_foreach_new (auto&& px, img.new_pixels())
{
......@@ -256,8 +257,8 @@ void LUT_C_Reversed(const mln::uint8* LUT, const mln::uint8* __restrict__ ibuffe
}
}
void LUT_New_Values_Reversed(const mln::uint8 LUT[], const mln::image2d<mln::uint8>& input,
mln::image2d<mln::uint8>& output)
void LUT_New_Values_Reversed(const mln::uint8 LUT[], const mln::experimental::image2d<mln::uint8>& input,
mln::experimental::image2d<mln::uint8>& output)
{
auto zipped_values = mln::ranges::view::zip(mln::ranges::view::reverse(input.new_values()),
mln::ranges::view::reverse(output.new_values()));
......@@ -270,8 +271,8 @@ void LUT_New_Values_Reversed(const mln::uint8 LUT[], const mln::image2d<mln::uin
}
}
void LUT_New_Pixels_Reversed(const mln::uint8 LUT[], const mln::image2d<mln::uint8>& input,
mln::image2d<mln::uint8>& output)
void LUT_New_Pixels_Reversed(const mln::uint8 LUT[], const mln::experimental::image2d<mln::uint8>& input,
mln::experimental::image2d<mln::uint8>& output)
{
auto zipped_pixels = mln::ranges::view::zip(mln::ranges::view::reverse(input.new_pixels()),
mln::ranges::view::reverse(output.new_pixels()));
......
......@@ -43,6 +43,8 @@ void Threshold_Inplace_New_Pixels(mln::experimental::image2d<uint8_t>& img);
void LUT_Inplace_New_Pixels(const uint8_t LUT[], mln::experimental::image2d<uint8_t>& img);
void Mult_Inplace_Reversed(mln::image2d<uint8_t>& img);
void Threshold_Inplace_Reversed(mln::image2d<uint8_t>& img);
void LUT_Inplace_Reversed(const uint8_t* LUT, mln::image2d<uint8_t>& img);
......@@ -60,24 +62,24 @@ void Threshold_C_Reversed(const uint8_t* ibuffer, uint8_t* obuffer, int width, i
void LUT_C_Reversed(const uint8_t* LUT, const uint8_t* ibuffer, uint8_t* obuffer, int width, int height,
std::ptrdiff_t stride);
void Mult_New_Values_Reversed(const mln::image2d<uint8_t>& input, mln::image2d<uint8_t>& output);
void Mult_New_Pixels_Reversed(const mln::image2d<uint8_t>& input, mln::image2d<uint8_t>& output);
void Mult_New_Values_Reversed(const mln::experimental::image2d<uint8_t>& input, mln::experimental::image2d<uint8_t>& output);
void Mult_New_Pixels_Reversed(const mln::experimental::image2d<uint8_t>& input, mln::experimental::image2d<uint8_t>& output);
void Threshold_New_Values_Reversed(const mln::image2d<uint8_t>& input, mln::image2d<uint8_t>& output);
void Threshold_New_Pixels_Reversed(const mln::image2d<uint8_t>& input, mln::image2d<uint8_t>& output);
void Threshold_New_Values_Reversed(const mln::experimental::image2d<uint8_t>& input, mln::experimental::image2d<uint8_t>& output);
void Threshold_New_Pixels_Reversed(const mln::experimental::image2d<uint8_t>& input, mln::experimental::image2d<uint8_t>& output);
void LUT_New_Values_Reversed(const uint8_t* LUT, const mln::image2d<uint8_t>& input,
mln::image2d<uint8_t>& output);
void LUT_New_Pixels_Reversed(const uint8_t* LUT, const mln::image2d<uint8_t>& input,
mln::image2d<uint8_t>& output);
void LUT_New_Values_Reversed(const uint8_t* LUT, const mln::experimental::image2d<uint8_t>& input,
mln::experimental::image2d<uint8_t>& output);
void LUT_New_Pixels_Reversed(const uint8_t* LUT, const mln::experimental::image2d<uint8_t>& input,
mln::experimental::image2d<uint8_t>& output);
void Mult_Inplace_New_Values_Reversed(mln::image2d<uint8_t>& img);
void Threshold_Inplace_New_Values_Reversed(mln::image2d<uint8_t>& img);
void LUT_Inplace_New_Values_Reversed(const uint8_t LUT[], mln::image2d<uint8_t>& img);
void Mult_Inplace_New_Values_Reversed(mln::experimental::image2d<uint8_t>& img);
void Threshold_Inplace_New_Values_Reversed(mln::experimental::image2d<uint8_t>& img);
void LUT_Inplace_New_Values_Reversed(const uint8_t LUT[], mln::experimental::image2d<uint8_t>& img);
void Mult_Inplace_New_Pixels_Reversed(mln::image2d<uint8_t>& img);
void Threshold_Inplace_New_Pixels_Reversed(mln::image2d<uint8_t>& img);
void LUT_Inplace_New_Pixels_Reversed(const uint8_t LUT[], mln::image2d<uint8_t>& img);
void Mult_Inplace_New_Pixels_Reversed(mln::experimental::image2d<uint8_t>& img);
void Threshold_Inplace_New_Pixels_Reversed(mln::experimental::image2d<uint8_t>& img);
void LUT_Inplace_New_Pixels_Reversed(const uint8_t LUT[], mln::experimental::image2d<uint8_t>& img);
class BMReferenceLinear : public benchmark::Fixture
......@@ -381,12 +383,12 @@ BENCHMARK_F(BMReferenceLinear, LUT_Reversed)(benchmark::State& st)
BENCHMARK_F(BMReferenceLinear, LUT_New_Values_Reversed)(benchmark::State& st)
{
runit(st, fun2_t([&](auto&&... args) { LUT_New_Values_Reversed(m_lut.data(), args...); }));
runit(st, fun6_t([&](auto&&... args) { LUT_New_Values_Reversed(m_lut.data(), args...); }));
}
BENCHMARK_F(BMReferenceLinear, LUT_New_Pixels_Reversed)(benchmark::State& st)
{
runit(st, fun2_t([&](auto&&... args) { LUT_New_Pixels_Reversed(m_lut.data(), args...); }));
runit(st, fun6_t([&](auto&&... args) { LUT_New_Pixels_Reversed(m_lut.data(), args...); }));
}
BENCHMARK_F(BMReferenceLinear, LUT_Inplace_C_Reversed)(benchmark::State& st)
......@@ -401,12 +403,12 @@ BENCHMARK_F(BMReferenceLinear, LUT_Inplace_Reversed)(benchmark::State& st)
BENCHMARK_F(BMReferenceLinear, LUT_Inplace_New_Values_Reversed)(benchmark::State& st)
{
runit(st, fun1_t([&](auto&&... args) { LUT_Inplace_New_Values_Reversed(m_lut.data(), args...); }));
runit(st, fun5_t([&](auto&&... args) { LUT_Inplace_New_Values_Reversed(m_lut.data(), args...); }));
}
BENCHMARK_F(BMReferenceLinear, LUT_Inplace_New_Pixels_Reversed)(benchmark::State& st)
{
runit(st, fun1_t([&](auto&&... args) { LUT_Inplace_New_Pixels_Reversed(m_lut.data(), args...); }));
runit(st, fun5_t([&](auto&&... args) { LUT_Inplace_New_Pixels_Reversed(m_lut.data(), args...); }));
}
......
......@@ -15,7 +15,7 @@ class Pylene(ConanFile):
default_options = ("gtest=False", "benchmark=False", "freeimage=False", "boost=False",
# TO REMOVE once docker image is fixed with the buildfarm profile updated
"boost_program_options=False")
generators = "cmake_paths"
generators = [ "cmake_paths", "cmake_find_package" ]
exports_sources = ["pylene/*", "cmake/*", "CMakeLists.txt", "LICENSE"]
def get_cmake_config(self):
......@@ -39,9 +39,8 @@ class Pylene(ConanFile):
# Requirements part of the INTERFACE
def requirements(self):
self.requires("range-v3/0.5.0@lrde/patched")
self.requires("cmcstl2/head@lrde/testing")
self.requires("fmt/5.3.0@bincrafters/stable")
self.requires("range-v3/0.9.1@ericniebler/stable")
self.requires("fmt/6.0.0")
if self.options.freeimage:
self.requires("freeimage/3.18.0@dutiona/stable")
......
#pragma once
#include <mln/core/image/experimental/ndimage_fwd.hpp>
#include <mln/core/image/experimental/ndbuffer_image.hpp>
#include <mln/core/image/image.hpp>
#include <mln/core/rangev3/rows.hpp>
#include <mln/core/rangev3/view/zip.hpp>
#include <mln/io/imprint.hpp>
#include <mln/io/experimental/imprint.hpp>
#include <range/v3/begin_end.hpp>
#include <string>
#include <functional>
#include <algorithm>
#include <type_traits>
#include <gtest/gtest.h>
......@@ -72,9 +76,11 @@ namespace fixtures::ImageCompare
msg << "The following images differ:\n";
else
msg << "The following images are identical:\n";
mln::io::imprint(reference, msg);
msg << " and\n:";
mln::io::imprint(input, msg);
(void)input;
(void)reference;
// mln::io::imprint(reference, msg);
// msg << " and\n:";
// mln::io::imprint(input, msg);
return msg.str();
}
} // namespace impl
......@@ -91,7 +97,9 @@ namespace fixtures::ImageCompare
/// Type-erased implementation for ndimages
::testing::AssertionResult compare(const mln::ndbuffer_image& a,
const mln::ndbuffer_image& b,
int comparison_flags);
int comparison_flags,
std::function<int(const void* a, const void* b, std::size_t n)> linecmp_fn,
std::function<void(const mln::ndbuffer_image&)> print_fn);
/// Best-match implementation for ndimages (forwarding to the type-erased one)
......@@ -100,8 +108,33 @@ namespace fixtures::ImageCompare
const mln::__ndbuffer_image<TB, bdim>& b,
int comparison_flags)
{
std::function<void(mln::ndbuffer_image)> print_fn;
std::function<int(const void* a, const void* b, std::size_t n)> linecmp_fn;
if constexpr (fmt::internal::has_formatter<TA, fmt::format_context>() &&
fmt::internal::has_formatter<TB, fmt::format_context>())
{
print_fn = [](const mln::ndbuffer_image& ima) {
if (const auto* a = ima.cast_to<TA, adim>())
mln::io::experimental::imprint(*a);
else if (const auto* b = ima.cast_to<TB, bdim>())
mln::io::experimental::imprint(*b);
};
}
// If value types are the same and they are tricially copyable, we will use memcpy
// Otherwise, we type-erase the comparison function
if constexpr (!(std::is_same_v<TA, TB> && std::is_trivially_copyable_v<TA>))
{
linecmp_fn = [](const void* a, const void* b, std::size_t n) -> int {
return !std::equal(reinterpret_cast<const TA*>(a), reinterpret_cast<const TA*>(a) + n,
reinterpret_cast<const TA*>(b));
};
}
return compare(static_cast<const mln::ndbuffer_image&>(a),
static_cast<const mln::ndbuffer_image&>(b), comparison_flags);
static_cast<const mln::ndbuffer_image&>(b),
comparison_flags, linecmp_fn, print_fn);
}
template <class ImageA, class ImageB>
......@@ -130,6 +163,7 @@ namespace fixtures::ImageCompare
return testing::AssertionFailure() << "The domains of A and B differ.";
}
{
auto zipped_vals = mln::ranges::view::zip(f.new_values(), g.new_values());
for (auto&& r : mln::ranges::rows(zipped_vals))
......@@ -137,6 +171,7 @@ namespace fixtures::ImageCompare
if (f_v != g_v)
return testing::AssertionFailure() << "The values of image A and B differ";
}
return ::testing::AssertionSuccess();
}
......
......@@ -5,7 +5,10 @@
namespace fixtures::ImageCompare::experimental::impl
{
::testing::AssertionResult compare(const mln::ndbuffer_image& a, const mln::ndbuffer_image& b, int comparaison_flags)
// Compare two buffer-encoded images
::testing::AssertionResult compare(const mln::ndbuffer_image& a, const mln::ndbuffer_image& b, int comparaison_flags,
std::function<int(const void* a, const void* b, std::size_t n)> linecmp_fn,
std::function<void(const mln::ndbuffer_image&)> print_fn)
{
mln::ndbuffer_image A = a;
mln::ndbuffer_image B = b;
......@@ -34,11 +37,16 @@ namespace fixtures::ImageCompare::experimental::impl
mln::sample_type_id id = a.sample_type();
if (id == mln::sample_type_id::OTHER)
return ::testing::AssertionFailure() << "A and B value type is not trivially comparable."; // Cannot be memcmp
std::size_t n = a.width() * mln::get_sample_type_id_traits(id).size();
// If the comparison function is not provided, try memcmp
if (!linecmp_fn)
{
if (id == mln::sample_type_id::OTHER)
return ::testing::AssertionFailure() << "A and B value type are not trivially comparable."; // Cannot be memcmp
linecmp_fn = std::memcmp;
}
std::size_t n = a.width() * mln::get_sample_type_id_traits(id).size();
auto a_buf = A.buffer();
auto b_buf = B.buffer();
......@@ -49,8 +57,21 @@ namespace fixtures::ImageCompare::experimental::impl
{
const std::byte* alineptr = a_buf + y * a.byte_stride(1) + z * a.byte_stride(2) + w * a.byte_stride(3);
const std::byte* blineptr = b_buf + y * b.byte_stride(1) + z * b.byte_stride(2) + w * b.byte_stride(3);
if (memcmp(alineptr, blineptr, n) != 0)
if (linecmp_fn(alineptr, blineptr, n) != 0)
{
if (print_fn)
{
fmt::print("With A = \n");
print_fn(a);
fmt::print(" and B = \n");
print_fn(b);
}
else
{
fmt::print("<Input images not printable.\n>");
}
return ::testing::AssertionFailure() << "The lines " << y << " differ.";
}
}
return ::testing::AssertionSuccess();
......
include(CMakePackageConfigHelpers)
find_package(Boost 1.58 REQUIRED)
find_package(range-v3 0.5.0 REQUIRED)
find_package(FreeImage REQUIRED)
find_package(TBB)
find_package(fmt)
find_package(range-v3 0.9.1 REQUIRED)
find_package(fmt 6.0 REQUIRED)
set(PYLENE_USE_TBB YES CACHE BOOL "Set to NO to disable use of TBB and parallelization")
......@@ -34,7 +35,7 @@ target_include_directories(Pylene SYSTEM PUBLIC ${Boost_INCLUDE_DIR})
target_include_directories(Pylene PUBLIC ${FreeImage_INCLUDE_DIRS})
set_property(TARGET Pylene APPEND
PROPERTY INTERFACE_LINK_DIRECTORIES ${FreeImage_LIBRARY_DIR} ${Boost_LIBRARY_DIRS})
target_link_libraries(Pylene PUBLIC range-v3)
target_link_libraries(Pylene PUBLIC range-v3::range-v3)
target_link_libraries(Pylene PUBLIC fmt::fmt)
......@@ -62,13 +63,18 @@ target_sources(Pylene PRIVATE
# Compiler configurations
target_compile_features(Pylene PUBLIC cxx_std_17)
target_compile_options(Pylene PUBLIC -fconcepts)
target_compile_definitions(Pylene PUBLIC PYLENE_CONCEPT_TS_ENABLED)
# Add concepts support for gcc > 8 with -fconcepts
if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8)
set(PYLENE_CONCEPT_TS_ENABLED True PARENT_SCOPE)
find_package(cmcstl2 REQUIRED)
target_link_libraries(Pylene PUBLIC stl2) # This add appropriate -fconcept flags
target_compile_definitions(Pylene PUBLIC PYLENE_CONCEPT_TS_ENABLED)
endif ()
# if (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8)
# set(PYLENE_CONCEPT_TS_ENABLED True PARENT_SCOPE)
# find_package(cmcstl2 REQUIRED)
# target_link_libraries(Pylene PUBLIC stl2) # This add appropriate -fconcept flags