diff --git a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX2.h b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX2.h index 61d10801e2..7c77f1881d 100644 --- a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX2.h +++ b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX2.h @@ -169,7 +169,7 @@ class Compressor_RgbEuclidean_x64_AVX2{ __m256i sum_sqr = _mm256_add_epi32(r, g); sum_sqr = _mm256_add_epi32(sum_sqr, b); - __m256i cmp = _mm256_cmpgt_epi32(m_distance_squared, sum_sqr); + __m256i cmp = _mm256_cmpeq_epi32(_mm256_min_epu32(sum_sqr, m_distance_squared), sum_sqr); return _mm256_movemask_ps(_mm256_castsi256_ps(cmp)); } diff --git a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX512.h b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX512.h index a86b23ce6f..b175f2bada 100644 --- a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX512.h +++ b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_AVX512.h @@ -168,7 +168,7 @@ class Compressor_RgbEuclidean_x64_AVX512{ __m512i sum_sqr = _mm512_add_epi32(r, g); sum_sqr = _mm512_add_epi32(sum_sqr, b); - __mmask16 cmp = _mm512_cmpgt_epi32_mask(m_distance_squared, sum_sqr); + __mmask16 cmp = _mm512_cmple_epu32_mask(sum_sqr, m_distance_squared); return cmp; } diff --git a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_SSE42.h b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_SSE42.h index 8e1ff3a117..f575461e76 100644 --- a/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_SSE42.h +++ b/SerialPrograms/Source/Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters_x64_SSE42.h @@ -188,7 +188,7 @@ class Compressor_RgbEuclidean_x64_SSE41{ __m128i sum_sqr = _mm_add_epi32(r, g); sum_sqr = _mm_add_epi32(sum_sqr, b); - __m128i cmp = _mm_cmpgt_epi32(m_distance_squared, sum_sqr); + __m128i cmp = _mm_cmpeq_epi32(_mm_min_epu32(sum_sqr, m_distance_squared), sum_sqr); return _mm_movemask_ps(_mm_castsi128_ps(cmp)); } diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.cpp b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.cpp new file mode 100644 index 0000000000..9f97f538a0 --- /dev/null +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.cpp @@ -0,0 +1,400 @@ +/* Image Filters RGB32 Euclidean Tests + * + * From: https://github.com/PokemonAutomation/ + * + * Checks every ISA's Euclidean distance filters against a scalar reference. + * A pixel is in range when the sum of the squared differences of its R, G + * and B to the expected color is <= the squared distance limit (rounded down + * to an integer). Alpha is ignored. + * + * Most test pixels sit exactly at, one below, or one above the squared limit, + * so an implementation that gets the boundary wrong fails. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "Common/Cpp/CancellableScope.h" +#include "Common/Cpp/CpuId/CpuId.h" +#include "Common/Cpp/Containers/AlignedVector.tpp" +#include "Common/Cpp/TestRunners/UnitTestDatabase.h" +#include "Kernels/BinaryMatrix/Kernels_BinaryMatrix.h" +#include "Kernels/BinaryImageFilters/Kernels_BinaryImage_BasicFilters.h" +#include "Kernels_ImageFilter_RGB32_Euclidean_Tests.h" + +namespace PokemonAutomation{ +namespace Kernels{ + + + +using FilterRgb32Euclidean = size_t (*)( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, bool replace_color_within_range, + uint32_t expected, double max_euclidean_distance +); +using ToBlackWhiteRgb32Euclidean = size_t (*)( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + bool in_range_black, + uint32_t expected, double max_euclidean_distance +); + +size_t filter_rgb32_euclidean_Default( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, bool replace_color_within_range, + uint32_t expected, double max_euclidean_distance +); +size_t to_blackwhite_rgb32_euclidean_Default( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + bool in_range_black, + uint32_t expected, double max_euclidean_distance +); +#ifdef PA_AutoDispatch_x64_08_Nehalem +size_t filter_rgb32_euclidean_x64_SSE42( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, bool replace_color_within_range, + uint32_t expected, double max_euclidean_distance +); +size_t to_blackwhite_rgb32_euclidean_x64_SSE42( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + bool in_range_black, + uint32_t expected, double max_euclidean_distance +); +#endif +#ifdef PA_AutoDispatch_x64_13_Haswell +size_t filter_rgb32_euclidean_x64_AVX2( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, bool replace_color_within_range, + uint32_t expected, double max_euclidean_distance +); +size_t to_blackwhite_rgb32_euclidean_x64_AVX2( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + bool in_range_black, + uint32_t expected, double max_euclidean_distance +); +#endif +#ifdef PA_AutoDispatch_x64_17_Skylake +size_t filter_rgb32_euclidean_x64_AVX512( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, bool replace_color_within_range, + uint32_t expected, double max_euclidean_distance +); +size_t to_blackwhite_rgb32_euclidean_x64_AVX512( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + bool in_range_black, + uint32_t expected, double max_euclidean_distance +); +#endif +#ifdef PA_AutoDispatch_arm64_20_M1 +size_t filter_rgb32_euclidean_ARM64_NEON( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + uint32_t replacement, bool replace_color_within_range, + uint32_t expected, double max_euclidean_distance +); +size_t to_blackwhite_rgb32_euclidean_ARM64_NEON( + const uint32_t* in, size_t in_bytes_per_row, size_t width, size_t height, + uint32_t* out, size_t out_bytes_per_row, + bool in_range_black, + uint32_t expected, double max_euclidean_distance +); +#endif + + + +namespace{ + +// R = 122, G = 128, B = 134: every test offset (at most 120 per channel) +// stays inside 0..255. +const uint32_t EXPECTED_COLOR = 0xff7a8086; +const int MAX_OFFSET = 120; +const uint32_t REPLACEMENT_COLOR = 0x13572468; + +const double MAX_DISTANCES[] = {0.0, 1.0, 50.0, 100.5}; + +// Widths around the SIMD vector sizes (4, 8, 16 pixels) and the binary +// matrix tile width (64 pixels), so the full words and the partial tails +// both see boundary pixels. +const size_t TEST_SIZES[][2] = { + {1, 1}, {2, 1}, {3, 2}, {4, 2}, {5, 3}, {7, 2}, {8, 2}, {9, 3}, + {15, 2}, {16, 2}, {17, 3}, {31, 2}, {32, 2}, {33, 2}, + {63, 2}, {64, 2}, {65, 3}, {100, 3}, {128, 2}, {129, 3}, {200, 5}, +}; + +struct Offset{ + int r; + int g; + int b; +}; + +int channel(uint32_t pixel, int shift){ + return (int)((pixel >> shift) & 0xff); +} +uint32_t distance_squared(uint32_t pixel){ + int r = channel(pixel, 16) - channel(EXPECTED_COLOR, 16); + int g = channel(pixel, 8) - channel(EXPECTED_COLOR, 8); + int b = channel(pixel, 0) - channel(EXPECTED_COLOR, 0); + return (uint32_t)(r * r + g * g + b * b); +} + +// Up to "limit" RGB offsets whose squared length is exactly "target". +void add_offsets(std::vector& offsets, uint32_t target, size_t limit){ + size_t added = 0; + for (int r = 0; r <= MAX_OFFSET && (uint32_t)(r * r) <= target; r++){ + for (int g = 0; g <= MAX_OFFSET && (uint32_t)(r * r + g * g) <= target; g++){ + uint32_t left = target - (uint32_t)(r * r + g * g); + int b = (int)std::lround(std::sqrt((double)left)); + if (b > MAX_OFFSET || (uint32_t)(b * b) != left){ + continue; + } + // Same length with other signs and channel orders. + offsets.push_back({ r, g, b}); + offsets.push_back({-r, g, -b}); + offsets.push_back({ g, -b, r}); + offsets.push_back({-b, -r, -g}); + added += 4; + if (added >= limit){ + return; + } + } + } +} + +AlignedVector make_image(double max_distance, size_t width, size_t height){ + uint32_t limit = (uint32_t)(max_distance * max_distance); + + std::vector boundary; + if (limit > 0){ + add_offsets(boundary, limit - 1, 16); + } + add_offsets(boundary, limit, 16); + add_offsets(boundary, limit + 1, 16); + + int spread = std::min((int)max_distance + 2, MAX_OFFSET); + + std::mt19937 generator((unsigned)(width * 1000003u + height * 7919u + limit)); + std::uniform_int_distribution pick(0, boundary.size() - 1); + std::uniform_int_distribution coin(0, 3); + std::uniform_int_distribution random_offset(-spread, spread); + std::uniform_int_distribution random_alpha(0, 255); + + AlignedVector image(width * height); + for (size_t c = 0; c < width * height; c++){ + // Three in four pixels are boundary cases, the rest are random + // colors near the expected one. + Offset offset = coin(generator) != 0 + ? boundary[pick(generator)] + : Offset{random_offset(generator), random_offset(generator), random_offset(generator)}; + uint32_t r = (uint32_t)(channel(EXPECTED_COLOR, 16) + offset.r); + uint32_t g = (uint32_t)(channel(EXPECTED_COLOR, 8) + offset.g); + uint32_t b = (uint32_t)(channel(EXPECTED_COLOR, 0) + offset.b); + image[c] = (random_alpha(generator) << 24) | (r << 16) | (g << 8) | b; + } + return image; +} + +std::string hex(uint32_t x){ + char buffer[16]; + std::snprintf(buffer, sizeof(buffer), "0x%08x", x); + return buffer; +} +std::string describe_case(double max_distance, size_t width, size_t height){ + char buffer[64]; + std::snprintf(buffer, sizeof(buffer), "max distance %g, %zux%zu", max_distance, width, height); + return buffer; +} +std::string describe_pixel(uint32_t pixel, size_t x, size_t y, uint32_t limit){ + return "pixel " + hex(pixel) + " at (" + std::to_string(x) + ", " + std::to_string(y) + + "), distance squared " + std::to_string(distance_squared(pixel)) + + ", limit " + std::to_string(limit); +} + + + +class Test_FilterRgb32Euclidean : public UnitTest{ +public: + Test_FilterRgb32Euclidean( + const std::string& arch_str, + FilterRgb32Euclidean filter, + ToBlackWhiteRgb32Euclidean to_blackwhite + ) + : UnitTest("Kernels::RGB32Euclidean - filter_" + arch_str) + , m_filter(filter) + , m_to_blackwhite(to_blackwhite) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + for (double max_distance : MAX_DISTANCES){ + uint32_t limit = (uint32_t)(max_distance * max_distance); + for (const auto& size : TEST_SIZES){ + scope.throw_if_cancelled(); + const size_t width = size[0]; + const size_t height = size[1]; + const size_t bytes_per_row = width * sizeof(uint32_t); + const std::string name = describe_case(max_distance, width, height); + + AlignedVector in = make_image(max_distance, width, height); + AlignedVector out(width * height); + + size_t expected_count = 0; + for (size_t c = 0; c < width * height; c++){ + expected_count += distance_squared(in[c]) <= limit; + } + + for (bool replace_color_within_range : {true, false}){ + size_t count = m_filter( + in.data(), bytes_per_row, width, height, + out.data(), bytes_per_row, + REPLACEMENT_COLOR, replace_color_within_range, + EXPECTED_COLOR, max_distance + ); + if (count != expected_count){ + return "filter, " + name + ": counted " + std::to_string(count) + + " pixels in range, expected " + std::to_string(expected_count); + } + for (size_t c = 0; c < width * height; c++){ + bool in_range = distance_squared(in[c]) <= limit; + uint32_t expected = in_range == replace_color_within_range ? REPLACEMENT_COLOR : in[c]; + if (out[c] != expected){ + return "filter, " + name + ", " + describe_pixel(in[c], c % width, c / width, limit) + + ": got " + hex(out[c]) + ", expected " + hex(expected); + } + } + } + + for (bool in_range_black : {true, false}){ + size_t count = m_to_blackwhite( + in.data(), bytes_per_row, width, height, + out.data(), bytes_per_row, + in_range_black, + EXPECTED_COLOR, max_distance + ); + if (count != expected_count){ + return "to_blackwhite, " + name + ": counted " + std::to_string(count) + + " pixels in range, expected " + std::to_string(expected_count); + } + for (size_t c = 0; c < width * height; c++){ + bool in_range = distance_squared(in[c]) <= limit; + uint32_t expected = in_range == in_range_black ? 0xff000000 : 0xffffffff; + if (out[c] != expected){ + return "to_blackwhite, " + name + ", " + describe_pixel(in[c], c % width, c / width, limit) + + ": got " + hex(out[c]) + ", expected " + hex(expected); + } + } + } + } + } + return true; + } + +private: + FilterRgb32Euclidean m_filter; + ToBlackWhiteRgb32Euclidean m_to_blackwhite; +}; + + + +class Test_CompressRgb32Euclidean : public UnitTest{ +public: + Test_CompressRgb32Euclidean(const std::string& matrix_str, BinaryMatrixType type) + : UnitTest("Kernels::RGB32Euclidean - compress_" + matrix_str) + , m_type(type) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + for (double max_distance : MAX_DISTANCES){ + uint32_t limit = (uint32_t)(max_distance * max_distance); + for (const auto& size : TEST_SIZES){ + scope.throw_if_cancelled(); + const size_t width = size[0]; + const size_t height = size[1]; + + AlignedVector in = make_image(max_distance, width, height); + std::unique_ptr matrix = make_PackedBinaryMatrix(m_type, width, height); + compress_rgb32_to_binary_euclidean( + in.data(), width * sizeof(uint32_t), *matrix, + EXPECTED_COLOR, max_distance + ); + + for (size_t y = 0; y < height; y++){ + for (size_t x = 0; x < width; x++){ + uint32_t pixel = in[x + y * width]; + bool expected = distance_squared(pixel) <= limit; + if (matrix->get(x, y) != expected){ + return "compress, " + describe_case(max_distance, width, height) + ", " + + describe_pixel(pixel, x, y, limit) + + ": got " + (expected ? "out of range" : "in range"); + } + } + } + } + } + return true; + } + +private: + BinaryMatrixType m_type; +}; + +} + + + +void add_tests_ImageFilter_RGB32_Euclidean(UnitTestDatabase& database){ + database.add( + "Default", filter_rgb32_euclidean_Default, to_blackwhite_rgb32_euclidean_Default + ); + database.add("64x4_Default", BinaryMatrixType::i64x4_Default); +#ifdef PA_AutoDispatch_x64_08_Nehalem + if (CPU_CAPABILITY_CURRENT.OK_08_Nehalem){ + database.add( + "x64_SSE42", filter_rgb32_euclidean_x64_SSE42, to_blackwhite_rgb32_euclidean_x64_SSE42 + ); + database.add("64x8_x64_SSE42", BinaryMatrixType::i64x8_x64_SSE42); + } +#endif +#ifdef PA_AutoDispatch_x64_13_Haswell + if (CPU_CAPABILITY_CURRENT.OK_13_Haswell){ + database.add( + "x64_AVX2", filter_rgb32_euclidean_x64_AVX2, to_blackwhite_rgb32_euclidean_x64_AVX2 + ); + database.add("64x16_x64_AVX2", BinaryMatrixType::i64x16_x64_AVX2); + } +#endif +#ifdef PA_AutoDispatch_x64_17_Skylake + if (CPU_CAPABILITY_CURRENT.OK_17_Skylake){ + database.add( + "x64_AVX512", filter_rgb32_euclidean_x64_AVX512, to_blackwhite_rgb32_euclidean_x64_AVX512 + ); + database.add("64x32_x64_AVX512", BinaryMatrixType::i64x32_x64_AVX512); + database.add("64x64_x64_AVX512", BinaryMatrixType::i64x64_x64_AVX512); + } +#endif +#ifdef PA_AutoDispatch_arm64_20_M1 + if (CPU_CAPABILITY_CURRENT.OK_M1){ + database.add( + "arm64_NEON", filter_rgb32_euclidean_ARM64_NEON, to_blackwhite_rgb32_euclidean_ARM64_NEON + ); + database.add("64x8_arm64_NEON", BinaryMatrixType::arm64x8_x64_NEON); + } +#endif +} + + + +} +} diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.h b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.h new file mode 100644 index 0000000000..38f996cd9d --- /dev/null +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.h @@ -0,0 +1,23 @@ +/* Image Filters RGB32 Euclidean Tests + * + * From: https://github.com/PokemonAutomation/ + * + */ + +#ifndef PokemonAutomation_Kernels_ImageFilter_RGB32_Euclidean_Tests_H +#define PokemonAutomation_Kernels_ImageFilter_RGB32_Euclidean_Tests_H + +#include "Common/Cpp/TestRunners/UnitTest.h" + +namespace PokemonAutomation{ +namespace Kernels{ + + + +void add_tests_ImageFilter_RGB32_Euclidean(UnitTestDatabase& database); + + + +} +} +#endif diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX2.cpp b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX2.cpp index dbf9de431f..46bfa24e0e 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX2.cpp +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX2.cpp @@ -47,7 +47,7 @@ class PixelTest_Rgb32Euclidean_x64_AVX2{ __m256i sum_sqr = _mm256_add_epi32(r, g); sum_sqr = _mm256_add_epi32(sum_sqr, b); - return _mm256_cmpgt_epi32(m_distance_squared, sum_sqr); + return _mm256_cmpeq_epi32(_mm256_min_epu32(sum_sqr, m_distance_squared), sum_sqr); } private: diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX512.cpp b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX512.cpp index 695c27c788..85fabfd865 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX512.cpp +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX512.cpp @@ -47,7 +47,7 @@ class PixelTest_Rgb32Euclidean_x64_AVX512{ __m512i sum_sqr = _mm512_add_epi32(r, g); sum_sqr = _mm512_add_epi32(sum_sqr, b); - return _mm512_cmpgt_epi32_mask(m_distance_squared, sum_sqr); + return _mm512_cmple_epu32_mask(sum_sqr, m_distance_squared); } private: diff --git a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_SSE42.cpp b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_SSE42.cpp index a9bef3ecf7..2ad53694f6 100644 --- a/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_SSE42.cpp +++ b/SerialPrograms/Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_SSE42.cpp @@ -60,7 +60,7 @@ class PixelTest_Rgb32Euclidean_x64_SSE42{ __m128i sum_sqr = _mm_add_epi32(r, g); sum_sqr = _mm_add_epi32(sum_sqr, b); - return _mm_cmpgt_epi32(m_distance_squared, sum_sqr); + return _mm_cmpeq_epi32(_mm_min_epu32(sum_sqr, m_distance_squared), sum_sqr); } private: diff --git a/SerialPrograms/Source/Kernels/Kernels_Tests.cpp b/SerialPrograms/Source/Kernels/Kernels_Tests.cpp index bcf950ab1e..328d6e063d 100644 --- a/SerialPrograms/Source/Kernels/Kernels_Tests.cpp +++ b/SerialPrograms/Source/Kernels/Kernels_Tests.cpp @@ -13,6 +13,7 @@ #include "AudioStreamConverter/Kernels_AudioStreamConverter.h" #include "BinaryMatrix/Kernels_BinaryMatrix_Tests.h" #include "ImageFilters/Kernels_ImageFilter_Tests.h" +#include "ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.h" #include "ImageScaleBrightness/Kernels_ImageScaleBrightness_Tests.h" #include "ImageStats/Kernels_ImageStats_Tests.h" #include "ScaleInvariantMatrixMatch/Kernels_ScaleInvariantMatrixMatch.h" @@ -33,6 +34,7 @@ void add_tests(UnitTestDatabase& database){ AudioStreamConverter::add_tests(database); add_tests_BinaryMatrix(database); add_tests_ImageFilters(database); + add_tests_ImageFilter_RGB32_Euclidean(database); add_tests_ImageScaleBrightness(database); add_tests_ImageStats(database); ScaleInvariantMatrixMatch::add_tests(database); diff --git a/SerialPrograms/cmake/SourceFiles.cmake b/SerialPrograms/cmake/SourceFiles.cmake index 4a370e7d9a..4d2edcc269 100644 --- a/SerialPrograms/cmake/SourceFiles.cmake +++ b/SerialPrograms/cmake/SourceFiles.cmake @@ -1137,6 +1137,8 @@ file(GLOB LIBRARY_SOURCES Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean.h Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_ARM64_NEON.cpp Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Default.cpp + Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.cpp + Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_Tests.h Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX2.cpp Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_AVX512.cpp Source/Kernels/ImageFilters/RGB32_EuclideanDistance/Kernels_ImageFilter_RGB32_Euclidean_x64_SSE42.cpp