diff --git a/test/parallel_api/numeric/numeric.ops/histogram.pass.cpp b/test/parallel_api/numeric/numeric.ops/histogram.pass.cpp index b16885cf8aa..de65083f81c 100644 --- a/test/parallel_api/numeric/numeric.ops/histogram.pass.cpp +++ b/test/parallel_api/numeric/numeric.ops/histogram.pass.cpp @@ -26,6 +26,96 @@ using namespace TestUtils; #if TEST_DPCPP_BACKEND_PRESENT +// Create a custom wrapped arithmetic type which does not implement conversion +// to the base type, but implements all the necessary arithmetic operations +// to implement the histogram kernel +template +struct wrapped_boundary +{ + wrapped_boundary(T bound) : boundary(bound) + {} + bool operator<(const T& other) + { + return boundary < other; + } + bool operator>(const T& other) + { + return other < *this; + } + bool operator>=(const T& other) + { + return !(*this < other); + } + bool operator<=(const T& other) + { + return !(other < *this); + } + + + bool operator<(const wrapped_boundary& other) + { + return boundary < other.boundary; + } + bool operator>(const wrapped_boundary& other) + { + return other < *this; + } + bool operator>=(const wrapped_boundary& other) + { + return !(*this < other); + } + bool operator<=(const wrapped_boundary& other) + { + return !(other < *this); + } + T boundary; + + friend + wrapped_boundary + operator-(const wrapped_boundary& wrap, const wrapped_boundary& other) + { + return wrapped_boundary{wrap.boundary - other.boundary}; + } + + friend + wrapped_boundary + operator+(const wrapped_boundary& wrap, const wrapped_boundary& other) + { + return wrapped_boundary{wrap.boundary + other.boundary}; + } + + friend + bool operator<(const T& other, const wrapped_boundary& wrap) + { + return other < wrap.boundary; + } + friend + bool operator>=(const T& other, const wrapped_boundary& wrap) + { + return !(other < wrap); + } + friend + bool operator<=(const T& other, const wrapped_boundary& wrap) + { + return !(wrap < other); + } + friend + bool operator>(const T& other, const wrapped_boundary& wrap) + { + return wrap < other; + } + + friend T operator-(const T& other, const wrapped_boundary& wrap) + { + return other - wrap.boundary; + } + + friend std::uint64_t operator/(const std::uint64_t& other, const wrapped_boundary& wrap) + { + return other / wrap.boundary; + } +}; + struct test_histogram_even_bins { template @@ -38,7 +128,46 @@ struct test_histogram_even_bins histogram_sequential(in_first, in_last, bin_size, bin_min, bin_max, expected_bin_first); auto orr = ::oneapi::dpl::histogram(exec, in_first, in_last, bin_size, bin_min, bin_max, bin_first); EXPECT_TRUE(bin_last == orr, "histogram returned wrong iterator"); - EXPECT_EQ_N(expected_bin_first, bin_first, bin_size, "wrong result from histogram"); + EXPECT_EQ_N(expected_bin_first, bin_first, bin_size, "wrong result from even bins histogram"); + ::std::fill_n(bin_first, bin_size, trash); + } +}; + +template +struct test_histogram_even_bins_extension_explicit_template +{ + template + void + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 expected_bin_first, + Iterator2 expected_bin_last, Iterator3 bin_first, Iterator3 bin_last, Size n, T bin_min, T bin_max, + Size trash) + { + const Size bin_size = bin_last - bin_first; + histogram_sequential(in_first, in_last, bin_size, bin_min, bin_max, expected_bin_first); + auto orr = ::oneapi::dpl::histogram(exec, in_first, in_last, bin_size, bin_min, + bin_max, bin_first); + EXPECT_TRUE(bin_last == orr, "histogram returned wrong iterator"); + EXPECT_EQ_N(expected_bin_first, bin_first, bin_size, "wrong result from explicit template histogram extension"); + ::std::fill_n(bin_first, bin_size, trash); + } +}; + +struct test_histogram_even_bins_extension_non_convertible +{ + template + void + operator()(Policy&& exec, Iterator1 in_first, Iterator1 in_last, Iterator2 expected_bin_first, + Iterator2 expected_bin_last, Iterator3 bin_first, Iterator3 bin_last, Size n, T bin_min, T bin_max, + Size trash) + { + const Size bin_size = bin_last - bin_first; + wrapped_boundary wrapped_bin_min{bin_min}; + wrapped_boundary wrapped_bin_max{bin_max}; + histogram_sequential(in_first, in_last, bin_size, wrapped_bin_min, wrapped_bin_max, expected_bin_first); + auto orr = ::oneapi::dpl::histogram(exec, in_first, in_last, bin_size, wrapped_bin_min, wrapped_bin_max, + bin_first); + EXPECT_TRUE(bin_last == orr, "histogram returned wrong iterator"); + EXPECT_EQ_N(expected_bin_first, bin_first, bin_size, "wrong result from non convertible histogram extension"); ::std::fill_n(bin_first, bin_size, trash); } }; @@ -56,12 +185,12 @@ struct test_histogram_range_bins histogram_sequential(in_first, in_last, boundary_first, boundary_last, expected_bin_first); auto orr = ::oneapi::dpl::histogram(exec, in_first, in_last, boundary_first, boundary_last, bin_first); EXPECT_TRUE(bin_last == orr, "histogram returned wrong iterator"); - EXPECT_EQ_N(expected_bin_first, bin_first, bin_size, "wrong result from histogram"); + EXPECT_EQ_N(expected_bin_first, bin_first, bin_size, "wrong result from custom range histogram"); ::std::fill_n(bin_first, bin_size, trash); } }; -template <::std::size_t CallNumber, typename Size, typename T> +template <::std::size_t CallNumber, typename ExplicitValueType, typename Size, typename T> void test_range_and_even_histogram(Size n, T min_boundary, T max_boundary, T overflow, Size jitter, Size num_bins, Size trash) @@ -74,11 +203,11 @@ test_range_and_even_histogram(Size n, T min_boundary, T max_boundary, T overflow Sequence expected(num_bins, [](size_t k) { return 0; }); Sequence out(num_bins, [&](size_t k) { return trash; }); - invoke_on_all_hetero_policies()(test_histogram_even_bins(), in.begin(), in.end(), expected.begin(), + invoke_on_all_hetero_policies()(test_histogram_even_bins(), in.begin(), in.end(), expected.begin(), expected.end(), out.begin(), out.end(), Size(in.size()), min_boundary, max_boundary, trash); # if !ONEDPL_FPGA_DEVICE - invoke_on_all_hetero_policies()(test_histogram_even_bins(), in.cbegin(), in.cend(), + invoke_on_all_hetero_policies()(test_histogram_even_bins(), in.cbegin(), in.cend(), expected.begin(), expected.end(), out.begin(), out.end(), Size(in.size()), min_boundary, max_boundary, trash); # endif // !ONEDPL_FPGA_DEVICE @@ -86,17 +215,40 @@ test_range_and_even_histogram(Size n, T min_boundary, T max_boundary, T overflow T offset = (max_boundary - min_boundary) / T(num_bins); Sequence boundaries(num_bins + 1, [&](size_t k) { return k * offset + (std::rand() % jitter) + min_boundary; }); - invoke_on_all_hetero_policies()(test_histogram_range_bins(), in.begin(), in.end(), + invoke_on_all_hetero_policies()(test_histogram_range_bins(), in.begin(), in.end(), boundaries.begin(), boundaries.end(), expected.begin(), expected.end(), out.begin(), out.end(), trash); # if !ONEDPL_FPGA_DEVICE - invoke_on_all_hetero_policies()(test_histogram_range_bins(), in.cbegin(), in.cend(), + invoke_on_all_hetero_policies()(test_histogram_range_bins(), in.cbegin(), in.cend(), boundaries.cbegin(), boundaries.cend(), expected.begin(), expected.end(), out.begin(), out.end(), trash); # endif // !ONEDPL_FPGA_DEVICE + + //test extension + + invoke_on_all_hetero_policies()(test_histogram_even_bins_extension_explicit_template{}, in.begin(), in.end(), expected.begin(), + expected.end(), out.begin(), out.end(), Size(in.size()), + min_boundary, max_boundary, trash); +# if !ONEDPL_FPGA_DEVICE + invoke_on_all_hetero_policies()(test_histogram_even_bins_extension_explicit_template{}, in.cbegin(), in.cend(), + expected.begin(), expected.end(), out.begin(), out.end(), + Size(in.size()), min_boundary, max_boundary, trash); +# endif // !ONEDPL_FPGA_DEVICE + + + invoke_on_all_hetero_policies()(test_histogram_even_bins_extension_non_convertible(), in.begin(), in.end(), expected.begin(), + expected.end(), out.begin(), out.end(), Size(in.size()), + min_boundary, max_boundary, trash); +# if !ONEDPL_FPGA_DEVICE + invoke_on_all_hetero_policies()(test_histogram_even_bins_extension_non_convertible(), in.cbegin(), in.cend(), + expected.begin(), expected.end(), out.begin(), out.end(), + Size(in.size()), min_boundary, max_boundary, trash); +# endif // !ONEDPL_FPGA_DEVICE + + } -template <::std::size_t CallNumber, typename T, typename Size> +template <::std::size_t CallNumber, typename T, typename Size, typename ExplicitValueType> void test_histogram(T min_boundary, T max_boundary, T overflow, Size jitter, Size trash) { @@ -104,7 +256,7 @@ test_histogram(T min_boundary, T max_boundary, T overflow, Size jitter, Size tra { for (Size n = 0; n <= 100000; n = n <= 16 ? n + 1 : Size(3.1415 * n)) { - test_range_and_even_histogram(n, min_boundary, max_boundary, overflow, jitter, bin_size, trash); + test_range_and_even_histogram(n, min_boundary, max_boundary, overflow, jitter, bin_size, trash); } } } @@ -114,10 +266,10 @@ int main() { #if TEST_DPCPP_BACKEND_PRESENT - test_histogram<0, float, uint32_t>(10000.0f, 110000.0f, 300.0f, uint32_t(50), uint32_t(99999)); + test_histogram<0, float, uint32_t, double>(10000.0f, 110000.0f, 300.0f, uint32_t(50), uint32_t(99999)); #if !ONEDPL_FPGA_DEVICE - test_histogram<1, std::int32_t, uint64_t>(-50000, 50000, 10000, uint64_t(5), uint64_t(99999)); + test_histogram<1, std::int32_t, uint64_t, std::int64_t>(-50000, 50000, 10000, uint64_t(5), uint64_t(99999)); #endif //!ONEDPL_FPGA_DEVICE #endif // TEST_DPCPP_BACKEND_PRESENT diff --git a/test/support/histogram_serial_impl.h b/test/support/histogram_serial_impl.h index 0427125682d..0374f31c536 100644 --- a/test/support/histogram_serial_impl.h +++ b/test/support/histogram_serial_impl.h @@ -17,17 +17,17 @@ #define _HISTOGRAM_SERIAL_IMPL_H template -::std::enable_if_t, ::std::uint32_t> +::std::enable_if_t, ::std::uint32_t> get_bin(T1 value, T2 min, T2 max, Size num_bins) { return ::std::uint32_t((::std::uint64_t(value - min) * ::std::uint64_t(num_bins)) / (max - min)); } template -::std::enable_if_t, ::std::uint32_t> +::std::enable_if_t, ::std::uint32_t> get_bin(T1 value, T2 min, T2 max, Size num_bins) { - return ::std::uint32_t((value - min) * (T1(num_bins) / (max - min))); + return ::std::uint32_t((value - min) * (T2(num_bins) / (max - min))); } template